library(QFeatures)
library(msqrob2)
library(dplyr)
library(tidyr)
library(tibble)
library(gt)
library(plotly)
library(stageR)
library(poolr)
library(RColorBrewer)
library(seqinr)
library(stringr)
library(ExploreModelMatrix)
library(data.table)

1 Import data

df <- read.csv("evidence.txt",header=TRUE, sep = ",")
#I can ignore the sigma proteins (those were just used for QC purposes)
df <- df %>% filter(!grepl("Sigma", df$Proteins))
#filter out phospho sites with less than 75% probability
#(other filtering options are possible)
filter_rows <- sapply(df$Phospho..STY..Probabilities, function(x){
  if (!x==""){
    prob <- str_extract_all(x,  "(?<=\\().+?(?=\\))")[[1]]
    if (!any(as.double(prob) > 0.75)){return(which(df$Phospho..STY..Probabilities == x))}
  }
}, USE.NAMES = F)
filter_rows <- unique(unlist(filter_rows))
nrow(df)
## [1] 178235
df <- df[-filter_rows,]
nrow(df)
## [1] 171780
#Now get format into wide format
df_wide <- pivot_wider(df, id_cols = c("Sequence", "Modifications", "Modified.sequence", "Proteins", "Leading.proteins",
                                        "Reverse", "Potential.contaminant", "Protein.group.IDs", "Leading.razor.protein"),
                                                                          #Is dat hier de beste manier om met 
                                                                          #gedupliceerde features om te gaan?
                       names_from = "Raw.file", names_prefix = "Intensity_", values_from = "Intensity", values_fn = max)
ecols <- grep("Intensity",colnames(df_wide))
#order dataframe by protein, for the normalisation step
df_wide = df_wide[order(df_wide$Leading.razor.protein),]
pe <- readQFeatures(df_wide,ecol= ecols,name="peptidoformRaw")
rownames(pe[["peptidoformRaw"]]) <- rowData(pe[["peptidoformRaw"]])$Modified.sequence

1.1 Experimental Layout

metadata <- read.csv("Experimental Design.csv")
colData(pe)$file <- sapply(str_split(rownames(colData(pe)), "_"), function(x) x[[2]])
metadata$File <- sub(x=metadata$File, pattern=".raw",replacement = "")
colData(pe)$condition <- sapply(colData(pe)$file, function(x){
  metadata[metadata$File==x,]$Condition
}, USE.NAMES = F)
colData(pe)$subset <- sapply(colData(pe)$file, function(x){
  metadata[metadata$File==x,]$Subset
}, USE.NAMES = F)
colData(pe)$condition <- case_when(grepl("A", colData(pe)$condition) ~ "A",
                                        TRUE ~ "B")
colData(pe)
## DataFrame with 90 rows and 3 columns
##                            file   condition      subset
##                     <character> <character> <character>
## Intensity_QX21595GM   QX21595GM           A           y
## Intensity_QX21643GM   QX21643GM           A           y
## Intensity_QX21469GM   QX21469GM           B           x
## Intensity_QX21484GM   QX21484GM           B           x
## Intensity_QX21487GM   QX21487GM           A           x
## ...                         ...         ...         ...
## Intensity_QX21782GM   QX21782GM           A           y
## Intensity_QX21794GM   QX21794GM           A           y
## Intensity_QX21803GM   QX21803GM           B           y
## Intensity_QX21806GM   QX21806GM           A           y
## Intensity_QX21812GM   QX21812GM           A           y
MSnbase::plotNA(assay(pe[["peptidoformRaw"]])) +
  xlab("Peptide index (ordered by data completeness)")
## Warning in fun(libname, pkgname): mzR has been built against a different Rcpp version (1.0.8.3)
## than is installed on your system (1.0.9). This might lead to errors
## when loading mzR. If you encounter such issues, please send a report,
## including the output of sessionInfo() to the Bioc support forum at 
## https://support.bioconductor.org/. For details see also
## https://github.com/sneumann/mzR/wiki/mzR-Rcpp-compiler-linker-issue.

2 Preprocessing

rowData(pe[["peptidoformRaw"]])$nNonZero <- rowSums(assay(pe[["peptidoformRaw"]]) > 0, na.rm = T)
pe <- zeroIsNA(pe, i = "peptidoformRaw")
pe <- filterFeatures(pe, ~Reverse != "+")
pe <- filterFeatures(pe, ~Potential.contaminant != "+")
pe <- logTransform(pe, base = 2, i = "peptidoformRaw", name = "peptidoformLog")
pe <- pe[rowData(pe[["peptidoformRaw"]])$nNonZero>2,,]
pe <- QFeatures::normalize(pe, method = "center.median", i = "peptidoformLog", name = "peptidoform")
colData(pe[["peptidoform"]]) <- colData(pe)

2.1 Normalisation via robust summarisation

pe <- aggregateFeatures(pe,
 i = "peptidoform",
 fcol = "Leading.razor.protein",
 na.rm = TRUE,
 name = "proteinRobust",
 fun = MsCoreUtils::robustSummary)
## Your quantitative data contain missing values. Please read the relevant
## section(s) in the aggregateFeatures manual page regarding the effects
## of missing values on data aggregation.
#Only take pepforms that have a parent protein
#(when there is no global profiling dataset, this will be all peptidoforms)
pepWithProtein <- rowData(pe[["peptidoform"]])$Proteins %in% rownames(pe[["proteinRobust"]])
pePepWithProtein  <- pe[["peptidoform"]][pepWithProtein,]
pe <- addAssay(pe,pePepWithProtein,"pepformRel")
#normalisation for protein abundance step
assay(pe[["pepformRel"]]) <- assay(pe[["pepformRel"]]) - assay(pe[["proteinRobust"]])[rowData(pe[["pepformRel"]])$Proteins,colnames(assay(pe[["pepformRel"]]))]
boxplot(assay(pe[["pepformRel"]]))

3 Differential peptidoform usage (DPFU)

3.1 Hypothesistest for each contrast

colData(pe)$condition <- relevel(as.factor(colData(pe)$condition), ref = "B")
colData(pe)$subset <- as.factor(colData(pe)$subset)
pe <- msqrob2::msqrob(object = pe, i = "pepformRel", formula = ~condition*subset, robust=FALSE)
## Warning: Zero sample variances detected, have been offset away from zero
rowData(pe[["pepformRel"]])$msqrobModels[[2]] %>%
                  getCoef
##        (Intercept)         conditionA            subsety conditionA:subsety 
##         -0.9008228          1.3425797          0.9384266         -1.1383736
fraction_of_ys <- (colData(pe) %>% as_tibble() %>% filter(subset == "y") %>% nrow()) / nrow(colData(pe))
contrasts <- c("conditionA", "conditionA + conditionA:subsety", "conditionA:subsety", "conditionA + 0.5 * conditionA:subsety", "conditionA + 0.6666667 * conditionA:subsety")
L <- makeContrast(c("conditionA = 0",
                    "conditionA + conditionA:subsety = 0",
                    "conditionA:subsety = 0",
                    "conditionA + 0.5 * conditionA:subsety = 0",
                    "conditionA + 0.6666667 * conditionA:subsety = 0"),
                  parameterNames = rowData(pe[["pepformRel"]])$msqrobModels[[2]] %>%
                  getCoef %>%
                  names)
pe <- hypothesisTest(object = pe, i = "pepformRel", contrast = L, overwrite = T)

3.1.1 Volcanoplot

volcano <- list()
for (contrast in contrasts){
volcano[[contrast]] <- rowData(pe[["pepformRel"]])[[contrast]]%>%
            ggplot(aes(x = logFC, y = -log10(pval), 
                   color = adjPval < 0.05,
                   annotation=rowData(pe[["pepformRel"]])[,3])) +
  geom_point(cex = 2.5) +
  scale_color_manual(values = alpha(c("black", "red"), 0.5)) + 
  theme_minimal() +
  ylab("-log10(pvalue)") +
  ggtitle(contrast)
}
volcano
## $conditionA
## Warning: Removed 687 rows containing missing values (geom_point).

## 
## $`conditionA + conditionA:subsety`
## Warning: Removed 687 rows containing missing values (geom_point).

## 
## $`conditionA:subsety`
## Warning: Removed 687 rows containing missing values (geom_point).

## 
## $`conditionA + 0.5 * conditionA:subsety`
## Warning: Removed 687 rows containing missing values (geom_point).

## 
## $`conditionA + 0.6666667 * conditionA:subsety`
## Warning: Removed 687 rows containing missing values (geom_point).

3.1.2 Significant peptidoforms for each contrast

tables <- list()
for (contrast in contrasts){
sigTable <- rowData(pe[["pepformRel"]])[[contrast]]
if(nrow(sigTable %>%
  na.exclude %>%
  filter(adjPval<0.05))>0){
sigTable <- sigTable %>%
  na.exclude %>%
  filter(adjPval<0.05) %>%
  arrange(pval) %>%
  mutate(
    se = format(se, digits = 2), 
    df = format(df, digits =2),
    t = format(t, digits = 2),
    adjPval = format(adjPval, digits = 3),
    rank = 1:length(logFC) 
  ) 
sigTable_print <- sigTable %>% mutate(peptidoform = rownames(sigTable)) %>% gt() %>% tab_header(title = md(contrast))
tables[[contrast]] <- sigTable
}
}
knitr::kable(tables)
logFC se df t pval adjPval rank
VGYVSGWGR -1.447473 0.3 37 -4.8 2.98e-05 0.0463 1
logFC se df t pval adjPval rank
VS(Phospho (STY))REFHSHEFHSHEDM(Oxidation (M))LVVDPK -1.3149071 0.30 71.6 -4.3 0.0000450 0.0361 1
EPQDTYHYLPFS(Phospho (STY))LPHR -1.6567618 0.36 34.6 -4.6 0.0000563 0.0361 2
LPIVNFDYS(Phospho (STY))M(Oxidation (M))EEK -0.7819471 0.19 75.6 -4.2 0.0000697 0.0361 3
LNVEDVDSTK 0.6265500 0.15 49.6 4.2 0.0001015 0.0395 4
AAM(Oxidation (M))VGMLANFLGFR -3.1281305 0.19 3.6 -16.4 0.0001530 0.0476 5
ADQTVLTEDEK 1.0553334 0.27 70.6 3.9 0.0001927 0.0500 6
logFC se df t pval adjPval rank
VGYVSGWGR -0.8150185 0.17 37 -4.9 2.01e-05 0.0313 1
logFC se df t pval adjPval rank
LPIVNFDYS(Phospho (STY))M(Oxidation (M))EEK -0.7089448 0.15 75.6 -4.6 0.0000153 0.0238 1
VGYVSGWGR -0.6042003 0.14 36.6 -4.4 0.0000812 0.0494 2
VS(Phospho (STY))REFHSHEFHSHEDM(Oxidation (M))LVVDPK -0.9902020 0.24 71.6 -4.1 0.0001164 0.0494 3
AAM(Oxidation (M))VGMLANFLGFR -2.4859751 0.14 3.6 -17.3 0.0001270 0.0494 4

4 DPTM

4.1 ptm summarisatie

4.1.1 Determine location of ptm

fasta <- "human.fasta"
parsed_fasta <- read.fasta(file = fasta, seqtype = "AA", as.string = T)
#modified sequence column contains _ that does not matter, but hinders location determining
rowData(pe[["pepformRel"]])$modified_sequence <- gsub("_", "", rowData(pe[["pepformRel"]])$Modified.sequence)
get_ptm_location <- function(feature, data, fasta, mod_column = "Modifications", 
                             peptide_seq_column = "Sequence", mod_seq_column = "modified_sequence", 
                             protein_column = "Leading.razor.protein", split = ",", collapse = ", "){
  prot <- data[feature,][[protein_column]]
  pep_seq <- data[feature,][[peptide_seq_column]]
  mod_seq <- data[feature,][[mod_seq_column]]
  prot_seq <- fasta[[prot]][1]

  #find location of peptide in protein
  #add -1 here, so that the addition of the location later on is correct
  pep_location <- unlist(lapply(gregexpr(pattern = pep_seq, prot_seq), min)) - 1
  final_mod <- c()
  j <- mod_seq
  #go over the modifications inside the modified sequence
  for(mod in regmatches(mod_seq, gregexpr("\\(.*?\\)\\)", mod_seq, perl=T))[[1]]){
    #find location of modification in peptide
    mod_location <- unlist(lapply(gregexpr(pattern = mod, j, fixed = T), min))
    #get location in protein (-1 because else it gives you the location after because of the presence of the modification in the string)
    location <- mod_location + pep_location -1
    #add location to modification
    mod_ <- paste(mod, location)
    #save modification
    final_mod <- c(final_mod, mod_)
    #now remove current modification from the sequence, so that we can continue to the next mod
    str_sub(j, mod_location, nchar(mod)+mod_location-1) <- ""
  }
  return(paste(final_mod, collapse = collapse))
}
rowData(pe[["pepformRel"]])$mod <- sapply(rownames(rowData(pe[["pepformRel"]])), function(x){
    get_ptm_location(x, rowData(pe[["pepformRel"]]), parsed_fasta)
}, USE.NAMES = F)
#Add ptm variable = protein + modification
rowData(pe[["pepformRel"]])$ptm <- ifelse(rowData(pe[["pepformRel"]])$mod != "",
                                               paste(rowData(pe[["pepformRel"]])$Leading.razor.protein, rowData(pe[["pepformRel"]])$mod, sep="_"), 
                                               "")

4.1.2 Get ptm level intensity matrix

Get all unique ptms present in the dataset (all protein - modification - location combinations)

prots <- unique(rowData(pe[["pepformRel"]])$Leading.razor.protein)
#Do for each protein
ptms <- sapply(prots, function(i) {
  pe_sub <- pe[["pepformRel"]][grepl(i, rowData(pe[["pepformRel"]])$Leading.razor.protein, fixed = T),]
  #pe_sub <- filterFeatures(pe,~grepl(Leading.razor.protein,pattern=i,fixed = T))
  #Get all unique modification present on that protein
  mods <- unique(unlist(strsplit(rowData(pe_sub)$mod, split = ", ", fixed = TRUE)))
  #Add protein info to mods
  ptm <- paste(rep(i, length(mods)), mods)
  #return all the protein-mods combinations
  ptm
})
ptms <- as.vector(unlist(ptms))
#For each ptm do
ptm_x_assay <- sapply(seq(1:length(ptms)), function(i){ 
  x <- ptms[i]
  #Get current protein and mod from ptm
  prot <- str_split(x, " ", 2)[[1]][1]
  current_ptm <- str_split(x, " ", 2)[[1]][2]
  #filter on that protein and on that mod to obtain all peptidoforms that correspond to the ptm
  pe_sub <- pe[["pepformRel"]][grepl(prot, rowData(pe[["pepformRel"]])$Leading.razor.protein, fixed = T),]
  #pe_sub <- filterFeatures(pe,~grepl(Leading.razor.protein,pattern=prot, fixed = T))
  ptm_sub <- pe_sub[grepl(current_ptm, rowData(pe_sub)$mod, fixed = T),]
  #ptm_sub <- filterFeatures(pe_sub,~grepl(mod,pattern=current_ptm, fixed=T))[["peptidoformNorm"]]
  #Get intensity values of those peptidoforms
  y <- assay(ptm_sub)
  #And summarise them to 1 row of intensity values: 1 value per sample for that ptm
  ptm_y <- try(MsCoreUtils::robustSummary(y), silent = T)
  if (is(ptm_y, "try-error")){
    ptm_y <- rep(NA, ncol(y))}
  ptm_y
})
## Warning in rlm.default(X, expression, ...): 'rlm' failed to converge in 20 steps

## Warning in rlm.default(X, expression, ...): 'rlm' failed to converge in 20 steps

## Warning in rlm.default(X, expression, ...): 'rlm' failed to converge in 20 steps

## Warning in rlm.default(X, expression, ...): 'rlm' failed to converge in 20 steps
#Then we get the intensity assay on ptm level
ptm_x_assay <- t(ptm_x_assay)
rownames(ptm_x_assay) <- ptms

4.1.3 Add to QFeatures object

Filter out ptms with all zero intensities

print(paste(nrow(ptm_x_assay), "ptms before filtering"))
## [1] "610 ptms before filtering"
filtering <- rowSums(ptm_x_assay != 0, na.rm=TRUE) > 0 
ptm_x_assay <- ptm_x_assay[filtering,]
print(paste(nrow(ptm_x_assay), "ptms after filtering"))
## [1] "471 ptms after filtering"
all(rownames(colData(pe)) == colnames(ptm_x_assay))
## [1] TRUE
rowdata <- data.frame(ptm = rownames(ptm_x_assay))
rowdata$protein <- sapply(str_split(rowdata$ptm, pattern=" "),function(x) x[1])
ptm_y_assay <- SummarizedExperiment(assays=as.matrix(ptm_x_assay), rowData=rowdata, colData=colData(pe))
pe <- addAssay(pe, ptm_y_assay, "ptmRel")

4.2 Hypothesistest for each contrast

pe <- msqrob2::msqrob(object = pe, i = "ptmRel", formula = ~condition*subset, robust=TRUE, overwrite = T)
## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps

## Warning in rlm.default(X, y, method = "M", maxit = maxitRob): 'rlm' failed to
## converge in 1 steps
rowData(pe[["ptmRel"]])$msqrobModels[[2]] %>%
                  getCoef
##        (Intercept)         conditionA            subsety conditionA:subsety 
##        -0.20364594         0.02035259        -0.03977042         0.02892887
contrasts <- c("conditionA", "conditionA + conditionA:subsety", "conditionA:subsety", "conditionA + 0.5 * conditionA:subsety", "conditionA + 0.6666667 * conditionA:subsety")
L <- makeContrast(c("conditionA = 0",
                    "conditionA + conditionA:subsety = 0",
                    "conditionA:subsety = 0",
                    "conditionA + 0.5 * conditionA:subsety = 0",
                    "conditionA + 0.6666667 * conditionA:subsety = 0"),   
                  parameterNames = rowData(pe[["ptmRel"]])$msqrobModels[[2]] %>%
                  getCoef %>%
                  names)
pe <- hypothesisTest(object = pe, i = "ptmRel", contrast = L, overwrite = T)

4.2.1 Volcanoplot

volcanos <- list()
for (contrast in contrasts){
library(plotly)
volcanos[[contrast]] <- 
  rowData(pe[["ptmRel"]])[[contrast]]%>%
  ggplot(aes(x = logFC, y = -log10(pval), 
             color = adjPval < 0.05,
             annotation=rowData(pe[["ptmRel"]])[,3])) +
  geom_point(cex = 2.5) +
  scale_color_manual(values = alpha(c("black", "red"), 0.5)) + theme_minimal() +
  ylab("-log10(pvalue)") +
  ggtitle(contrast)
}
volcanos
## $conditionA
## Warning: Removed 68 rows containing missing values (geom_point).

## 
## $`conditionA + conditionA:subsety`
## Warning: Removed 68 rows containing missing values (geom_point).

## 
## $`conditionA:subsety`
## Warning: Removed 68 rows containing missing values (geom_point).

## 
## $`conditionA + 0.5 * conditionA:subsety`
## Warning: Removed 68 rows containing missing values (geom_point).

## 
## $`conditionA + 0.6666667 * conditionA:subsety`
## Warning: Removed 68 rows containing missing values (geom_point).

4.2.2 Heatmap

We first select the names of the ptms that were declared signficant.

4.2.3 Significant ptms for each contrast

tables <- list()
for (contrast in contrasts){
sigTable <- rowData(pe[["ptmRel"]])[[contrast]]
if(nrow(sigTable %>%
  na.exclude %>%
  filter(adjPval<0.05)) > 0){
sigTable <- sigTable %>%
  na.exclude %>%
  filter(adjPval<0.05) %>%
  arrange(pval) %>%
  mutate(
    se = format(se, digits = 2), 
    df = format(df, digits =2),
    t = format(t, digits = 2),
    adjPval = format(adjPval, digits = 3),
    rank = 1:length(logFC) 
  ) 
sigTable_print <- sigTable %>% mutate(peptidoform = rownames(sigTable)) %>% gt() %>% tab_header(title = md(contrast))
tables[[contrast]] <- sigTable
}
}
knitr::kable(tables)
logFC se df t pval adjPval rank
sp|P01019|ANGT_HUMAN (Oxidation (M)) 105 -3.2887952 0.16 4.8 -20.8 0.0000068 0.00193 1
sp|P10909|CLUS_HUMAN (Phospho (STY)) 210 -1.6735301 0.33 32.9 -5.1 0.0000128 0.00193 2
sp|P10451|OSTP_HUMAN (Oxidation (M)) 284 -0.7650361 0.17 82.4 -4.6 0.0000144 0.00193 3
sp|P02765|FETUA_HUMAN (Oxidation (M)) 321 -1.2172094 0.29 68.9 -4.1 0.0000962 0.00969 4
sp|O94769|ECM2_HUMAN (Oxidation (M)) 76 -0.6949871 0.18 73.2 -3.9 0.0001927 0.01366 5
sp|P05060|SCG1_HUMAN (Phospho (STY)) 317 -0.8350259 0.21 62.4 -3.9 0.0002034 0.01366 6
sp|O94769|ECM2_HUMAN (Phospho (STY)) 75 -0.7307004 0.19 80.5 -3.8 0.0002810 0.01607 7
sp|P05060|SCG1_HUMAN (Phospho (STY)) 311 -0.7705091 0.20 81.8 -3.8 0.0003190 0.01607 8
sp|P62328|TYB4_HUMAN (Acetyl (Protein N-term)) 1 0.8411341 0.18 13.0 4.8 0.0003640 0.01630 9
sp|O94769|ECM2_HUMAN (Phospho (STY)) 245 0.4363289 0.12 68.0 3.6 0.0005450 0.02155 10
sp|P01042|KNG1_HUMAN (Phospho (STY)) 275 -1.3223296 0.35 33.2 -3.8 0.0005882 0.02155 11
sp|P10451|OSTP_HUMAN (Phospho (STY)) 280 -1.0756663 0.31 84.1 -3.5 0.0006994 0.02349 12
logFC se df t pval adjPval rank
sp|P10909|CLUS_HUMAN (Phospho (STY)) 210 -2.363970 0.52 32.9 -4.6 0.0000680 0.021 1
sp|P01019|ANGT_HUMAN (Oxidation (M)) 105 -2.440847 0.21 4.8 -11.7 0.0001041 0.021 2
logFC se df t pval adjPval rank
sp|P01019|ANGT_HUMAN (Oxidation (M)) 105 -2.0683715 0.10 4.8 -19.8 0.0000086 0.00349 1
sp|O94769|ECM2_HUMAN (Oxidation (M)) 76 -0.6015157 0.16 73.2 -3.9 0.0002451 0.03315 2
sp|P07197|NFM_HUMAN (Phospho (STY)) 736 -1.4251552 0.33 23.6 -4.3 0.0002739 0.03315 3
sp|Q14515|SPRL1_HUMAN (Oxidation (M)) 276 -1.5631381 0.38 29.1 -4.1 0.0003290 0.03315 4
logFC se df t pval adjPval rank
sp|P01019|ANGT_HUMAN (Oxidation (M)) 105 -2.4751795 0.11 4.8 -21.6 0.0000058 0.00232 1
sp|O94769|ECM2_HUMAN (Oxidation (M)) 76 -0.6326728 0.15 73.2 -4.3 0.0000450 0.00906 2
sp|P07197|NFM_HUMAN (Phospho (STY)) 736 -1.4166206 0.32 23.6 -4.4 0.0001969 0.02640 3
sp|P10451|OSTP_HUMAN (Oxidation (M)) 284 -0.5165387 0.14 82.4 -3.8 0.0002620 0.02640 4
sp|Q14515|SPRL1_HUMAN (Oxidation (M)) 276 -1.4812379 0.38 29.1 -3.9 0.0005106 0.03572 5
sp|O94769|ECM2_HUMAN (Phospho (STY)) 75 -0.5560719 0.16 80.5 -3.6 0.0006166 0.03572 6
sp|P02765|FETUA_HUMAN (Oxidation (M)) 321 -0.8730036 0.24 68.9 -3.6 0.0006205 0.03572 7
sp|P01042|KNG1_HUMAN (Phospho (STY)) 275 -1.0204569 0.28 33.2 -3.7 0.0008739 0.04240 8
sp|P05060|SCG1_HUMAN (Phospho (STY)) 311 -0.5699020 0.17 81.8 -3.4 0.0009469 0.04240 9
a = "sp|Q16610|ECM1_HUMAN (Phospho (STY)) 80"
b = "sp|P13611|CSPG2_HUMAN (Phospho (STY)) 2115"
tables <- list()
for (contrast in contrasts){
sigTable <- rowData(pe[["ptmRel"]])[[contrast]]
tables[[contrast]] <- sigTable %>% rownames_to_column("ptm") %>% filter(ptm==a|ptm==b)
}
knitr::kable(tables)
ptm logFC se df t pval adjPval
sp|P13611|CSPG2_HUMAN (Phospho (STY)) 2115 NA NA NA NA NA NA
sp|Q16610|ECM1_HUMAN (Phospho (STY)) 80 -0.2646351 0.1593109 29.40381 -1.661124 0.1073162 0.9935778
ptm logFC se df t pval adjPval
sp|P13611|CSPG2_HUMAN (Phospho (STY)) 2115 NA NA NA NA NA NA
sp|Q16610|ECM1_HUMAN (Phospho (STY)) 80 -0.0540587 0.1428702 29.40381 -0.3783766 0.707869 0.9965335
ptm logFC se df t pval adjPval
sp|P13611|CSPG2_HUMAN (Phospho (STY)) 2115 NA NA NA NA NA NA
sp|Q16610|ECM1_HUMAN (Phospho (STY)) 80 0.2105764 0.2139903 29.40381 0.9840464 0.3331211 0.9521619
ptm logFC se df t pval adjPval
sp|P13611|CSPG2_HUMAN (Phospho (STY)) 2115 NA NA NA NA NA NA
sp|Q16610|ECM1_HUMAN (Phospho (STY)) 80 -0.1593469 0.1069951 29.40381 -1.489291 0.1470595 0.7317265
ptm logFC se df t pval adjPval
sp|P13611|CSPG2_HUMAN (Phospho (STY)) 2115 NA NA NA NA NA NA
sp|Q16610|ECM1_HUMAN (Phospho (STY)) 80 -0.1242508 0.1090502 29.40381 -1.139391 0.2637373 0.7749193

5 PLOTS

5.1 Lineplots

5.1.1 PTM - level

ptm_list1 <- c()
for (contrast in contrasts){
sigTable <- rowData(pe[["ptmRel"]])[[contrast]] %>% filter(adjPval<0.05)
ptm_list1 <- c(ptm_list1, rownames(sigTable))
}
ptm_list1 <- unique(ptm_list1)

plots <- list()
for (i in ptm_list1){
prot_ = str_split(i, " ")[[1]][1]
site_ = str_split_fixed(i, " ", 2)[,2]

pepform_df <- longFormat(pe[,,"pepformRel"], rowvars = c("Leading.razor.protein", "ptm"), colvars = c("condition", "subset")) %>% as.data.frame()
pepform_df <- pepform_df %>% filter(Leading.razor.protein == prot_)
pepform_df <- pepform_df %>% filter(grepl(site_, ptm, fixed = T))
pepform_df$FeatureType <- "Peptide"
pepform_df <- pepform_df %>% arrange(condition, subset, rowname)

ptm_df <- longFormat(pe[,,"ptmRel"], rowvars = c("protein", "ptm"), colvars = c("condition", "subset")) %>% as.data.frame()
ptm_df <- ptm_df %>% filter(ptm == i)
ptm_df$FeatureType <- "PTM"
ptm_df <- ptm_df %>% arrange(condition, subset, rowname)

ptm_estimate <- ptm_df %>% select(c("primary", "colname", "condition", "subset")) %>%
                           mutate(rowname = paste(ptm_df$rowname, "estimate"),
                                  ptm = paste(ptm_df$ptm, "estimate"),
                                  Protein = paste(ptm_df$Protein, "estimate"),
                                  FeatureType = "PTM_estimated",
                                  value = NA,
                                  assay = "model")
fixeffects <- rowData(pe[["ptmRel"]])$msqrobModels[[unique(ptm_df$ptm)]] %>% getCoef
ptm_estimate[ptm_estimate$condition=="B"&(ptm_estimate$subset=="x"),]$value <- 
                                                    fixeffects[["(Intercept)"]]
ptm_estimate[ptm_estimate$condition=="B"&(ptm_estimate$subset=="y"),]$value <- 
   fixeffects[["(Intercept)"]] + fixeffects[["subsety"]]
ptm_estimate[ptm_estimate$condition=="A"&(ptm_estimate$subset=="x"),]$value <- 
   fixeffects[["(Intercept)"]] + fixeffects[["conditionA"]]
ptm_estimate[ptm_estimate$condition=="A"&(ptm_estimate$subset=="y"),]$value <- 
   fixeffects[["(Intercept)"]] + fixeffects[["conditionA"]] + fixeffects[["conditionA:subsety"]] + fixeffects[["subsety"]]

plot_df <- rbindlist(list(pepform_df, ptm_df, ptm_estimate), fill = TRUE)
plot_points <- rbindlist(list(pepform_df, ptm_df), fill = TRUE)

plot_df$primary <- forcats::fct_inorder(plot_df$primary)

plots[[i]] <- plot_df %>% ggplot() +
  geom_line(aes(x = primary, y = value , group = rowname, color = FeatureType), size = 2) +
  geom_point(data = plot_points, aes(x = primary, y = value , group = rowname, 
                                     color = FeatureType), size = 5) +
  geom_vline(data=data.frame(x = c(43.5, 17.5, 56.5)),
             aes(xintercept=as.numeric(x)), linetype = "dashed") +
  scale_colour_manual(values = c("Peptide" = "#C3C3C3", "PTM" = "palegreen3",
                                 "PTM_estimated" = "slateblue3")) +
  labs(title = i, x = "Sample", y = "Intensity") +
  theme_light() +
  theme(axis.text.x = element_text(angle = 60, hjust=1, size = 10),
        axis.text.y = element_text(size = 16),
        legend.text=element_text(size=19),
        axis.title.y = element_text(size = 16),
        axis.title.x = element_text(size = 16),
        title = element_text(size = 19),
        strip.text = element_text(size = 16),
        legend.title =  element_blank(),
        legend.direction = "horizontal",
        legend.position = c(0.5, 0.1)) +
  annotate("text", x = 24, y = 6.5, label = "B", size = 8) +
  annotate("text", x = 70, y = 6.5, label = "A", size = 8) +
  annotate("text", x = 9, y = 6, label = "x", size = 7) +
  annotate("text", x = 30, y = 6, label = "y", size = 7) +
  annotate("text", x = 49.5, y = 6, label = "x", size = 7) +
  annotate("text", x = 73, y = 6, label = "y", size = 7) +
  ylim(-6, 6.5)

}
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
plots
## $`sp|O94769|ECM2_HUMAN (Phospho (STY)) 75`
## Warning: Removed 13 rows containing missing values (geom_point).

## 
## $`sp|O94769|ECM2_HUMAN (Oxidation (M)) 76`
## Warning: Removed 22 rows containing missing values (geom_point).

## 
## $`sp|O94769|ECM2_HUMAN (Phospho (STY)) 245`
## Warning: Removed 4 row(s) containing missing values (geom_path).
## Warning: Removed 26 rows containing missing values (geom_point).

## 
## $`sp|P01019|ANGT_HUMAN (Oxidation (M)) 105`
## Warning: Removed 143 row(s) containing missing values (geom_path).
## Warning: Removed 252 rows containing missing values (geom_point).

## 
## $`sp|P01042|KNG1_HUMAN (Phospho (STY)) 275`
## Warning: Removed 6 row(s) containing missing values (geom_path).
## Warning: Removed 102 rows containing missing values (geom_point).

## 
## $`sp|P02765|FETUA_HUMAN (Oxidation (M)) 321`
## Warning: Removed 22 rows containing missing values (geom_point).

## 
## $`sp|P05060|SCG1_HUMAN (Phospho (STY)) 311`
## Warning: Removed 1 row(s) containing missing values (geom_path).
## Warning: Removed 60 rows containing missing values (geom_point).

## 
## $`sp|P05060|SCG1_HUMAN (Phospho (STY)) 317`
## Warning: Removed 7 row(s) containing missing values (geom_path).
## Warning: Removed 97 rows containing missing values (geom_point).

## 
## $`sp|P10451|OSTP_HUMAN (Oxidation (M)) 284`
## Warning: Removed 37 row(s) containing missing values (geom_path).
## Warning: Removed 290 rows containing missing values (geom_point).

## 
## $`sp|P10451|OSTP_HUMAN (Phospho (STY)) 280`
## Warning: Removed 28 row(s) containing missing values (geom_path).
## Warning: Removed 267 rows containing missing values (geom_point).

## 
## $`sp|P10909|CLUS_HUMAN (Phospho (STY)) 210`
## Warning: Removed 104 rows containing missing values (geom_point).

## 
## $`sp|P62328|TYB4_HUMAN (Acetyl (Protein N-term)) 1`
## Warning: Removed 26 row(s) containing missing values (geom_path).
## Warning: Removed 144 rows containing missing values (geom_point).

## 
## $`sp|P07197|NFM_HUMAN (Phospho (STY)) 736`
## Warning: Removed 120 rows containing missing values (geom_point).

## 
## $`sp|Q14515|SPRL1_HUMAN (Oxidation (M)) 276`
## Warning: Removed 26 row(s) containing missing values (geom_path).
## Warning: Removed 194 rows containing missing values (geom_point).

5.1.2 Peptidoform level

pepf_list1 <- c()
for (contrast in contrasts){
sigTable <- rowData(pe[["pepformRel"]])[[contrast]] %>% filter(adjPval<0.05)
pepf_list1 <- c(pepf_list1, rownames(sigTable))
}
pepf_list1 <- unique(pepf_list1)

plots <- list()
for (i in pepf_list1){
prot_ = rowData(pe[["pepformRel"]])[i,][["Leading.razor.protein"]]
site_ = rowData(pe[["pepformRel"]])[i,][["mod"]]
sites_ = strsplit(site_, ", ")[[1]]
for (site_ in sites_){
ptm_ = paste(prot_, site_, collapse = " ")
print(ptm_)

pepform_df <- longFormat(pe[,,"pepformRel"], rowvars = c("Leading.razor.protein", "ptm"), colvars = c("condition", "subset")) %>% as.data.frame()
pepform_df <- pepform_df %>% filter(Leading.razor.protein == prot_)
pepform_df <- pepform_df %>% filter(grepl(site_, ptm, fixed = T))
pepform_df$FeatureType <- "Peptide"
pepform_df[pepform_df$rowname==i,]$FeatureType <- "SignificantPeptide"
pepform_df <- pepform_df %>% arrange(condition, subset, rowname)

ptm_df <- longFormat(pe[,,"ptmRel"], rowvars = c("protein", "ptm"), colvars = c("condition", "subset")) %>% as.data.frame()
ptm_df <- ptm_df %>% filter(ptm == ptm_)
ptm_df$FeatureType <- "PTM"
ptm_df <- ptm_df %>% arrange(condition, subset, rowname)

ptm_estimate <- ptm_df %>% select(c("primary", "colname", "condition", "subset")) %>%
                           mutate(rowname = paste(ptm_df$rowname, "estimate"),
                                  ptm = paste(ptm_df$ptm, "estimate"),
                                  Protein = paste(ptm_df$Protein, "estimate"),
                                  FeatureType = "PTM_estimated",
                                  value = NA,
                                  assay = "model")
fixeffects <- rowData(pe[["ptmRel"]])$msqrobModels[[unique(ptm_df$ptm)]] %>% getCoef
ptm_estimate[ptm_estimate$condition=="B"&(ptm_estimate$subset=="x"),]$value <- 
                                                    fixeffects[["(Intercept)"]]
ptm_estimate[ptm_estimate$condition=="B"&(ptm_estimate$subset=="y"),]$value <- 
   fixeffects[["(Intercept)"]] + fixeffects[["subsety"]]
ptm_estimate[ptm_estimate$condition=="A"&(ptm_estimate$subset=="x"),]$value <- 
   fixeffects[["(Intercept)"]] + fixeffects[["conditionA"]]
ptm_estimate[ptm_estimate$condition=="A"&(ptm_estimate$subset=="y"),]$value <- 
   fixeffects[["(Intercept)"]] + fixeffects[["conditionA"]] + fixeffects[["conditionA:subsety"]]+ fixeffects[["subsety"]]


plot_df <- rbindlist(list(pepform_df, ptm_df, ptm_estimate), fill = TRUE)
plot_points <- rbindlist(list(pepform_df, ptm_df), fill = TRUE)

# plot_df[plot_df$FeatureType == 'PTM'][['FeatureType']] <- "PTM Summarized"
# plot_df[plot_df$FeatureType != 'PTM'][['FeatureType']] <- "PTM Feature"
plot_df$primary <- forcats::fct_inorder(plot_df$primary)

plots[[paste(i, site_)]] <- plot_df %>% ggplot() +
  geom_line(aes(x = primary, y = value , group = rowname, color = FeatureType), size =2) +
  geom_point(data = plot_points, aes(x = primary, y = value , group = rowname, color = FeatureType), size = 5) +
  geom_vline(data=data.frame(x = c(43.5, 17.5, 56.5)),
             aes(xintercept=as.numeric(x)), linetype = "dashed") +
  scale_colour_manual(values = c("Peptide" = "#C3C3C3", "PTM" = "palegreen3", 
                                 "SignificantPeptide" = "violetred1",
                                 "PTM_estimated" = "lightgoldenrod")) +
  labs(title = paste(i, ptm_), x = "Sample", y = "Intensity") +
  theme_light() +
  theme(axis.text.x = element_text(angle = 60, hjust=1, size = 10),
        axis.text.y = element_text(size = 16),
        legend.text=element_text(size=19),
        axis.title.y = element_text(size = 16),
        axis.title.x = element_text(size = 16),
        title = element_text(size = 19),
        strip.text = element_text(size = 16),
        legend.title =  element_blank(),
        legend.direction = "horizontal",
        legend.position = c(0.5, 0.1)) +
  annotate("text", x = 24, y = 6.5, label = "B", size = 8) +
  annotate("text", x = 70, y = 6.5, label = "A", size = 8) +
  annotate("text", x = 9, y = 6, label = "x", size = 7) +
  annotate("text", x = 30, y = 6, label = "y", size = 7) +
  annotate("text", x = 49.5, y = 6, label = "x", size = 7) +
  annotate("text", x = 73, y = 6, label = "y", size = 7) +
  ylim(-6, 6.5)
}
}
## [1] "sp|O94769|ECM2_HUMAN (Phospho (STY)) 75"
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## [1] "sp|O94769|ECM2_HUMAN (Oxidation (M)) 76"
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## [1] "sp|P01019|ANGT_HUMAN (Oxidation (M)) 105"
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## [1] "sp|P10451|OSTP_HUMAN (Phospho (STY)) 270"
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## [1] "sp|P10451|OSTP_HUMAN (Oxidation (M)) 284"
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## [1] "sp|P10909|CLUS_HUMAN (Phospho (STY)) 210"
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
## Warning: 'experiments' dropped; see 'metadata'
## harmonizing input:
##   removing 450 sampleMap rows not in names(experiments)
plots
## $`_LPIVNFDYS(Phospho (STY))M(Oxidation (M))EEK_ (Phospho (STY)) 75`
## Warning: Removed 13 rows containing missing values (geom_point).

## 
## $`_LPIVNFDYS(Phospho (STY))M(Oxidation (M))EEK_ (Oxidation (M)) 76`
## Warning: Removed 22 rows containing missing values (geom_point).

## 
## $`_AAM(Oxidation (M))VGMLANFLGFR_ (Oxidation (M)) 105`
## Warning: Removed 143 row(s) containing missing values (geom_path).
## Warning: Removed 252 rows containing missing values (geom_point).

## 
## $`_VS(Phospho (STY))REFHSHEFHSHEDM(Oxidation (M))LVVDPK_ (Phospho (STY)) 270`
## Warning: Removed 35 row(s) containing missing values (geom_path).
## Warning: Removed 240 rows containing missing values (geom_point).

## 
## $`_VS(Phospho (STY))REFHSHEFHSHEDM(Oxidation (M))LVVDPK_ (Oxidation (M)) 284`
## Warning: Removed 37 row(s) containing missing values (geom_path).
## Warning: Removed 290 rows containing missing values (geom_point).

## 
## $`_EPQDTYHYLPFS(Phospho (STY))LPHR_ (Phospho (STY)) 210`
## Warning: Removed 104 rows containing missing values (geom_point).

LS0tDQp0aXRsZTogInBob3NwaG9EYXRhc2V0IG1zcXJvYlBUTSB3aXRob3V0IEdQIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHRoZW1lOiBjb3Ntbw0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiB5ZXMNCiAgICBoaWdobGlnaHQ6IHRhbmdvDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICBkZl9wcmludDogcGFnZWQNCiAgcGRmX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAnNCcNCi0tLQ0KDQpgYGB7ciwgc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19rbml0JHNldChyb290LmRpciA9ICJDOi9Vc2Vycy9OaW5hL09uZURyaXZlIC0gVUdlbnQvRG9jdW1lbnRlbi9Eb2N0b3JhYXQvbXNxcm9iUFRNIHBhcGVyL2Jpb2xvZ2ljYWwgcGhvc3BobyBkYXRhc2V0LyIpDQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRX0NCmxpYnJhcnkoUUZlYXR1cmVzKQ0KbGlicmFyeShtc3Fyb2IyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KHRpYmJsZSkNCmxpYnJhcnkoZ3QpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoc3RhZ2VSKQ0KbGlicmFyeShwb29scikNCmxpYnJhcnkoUkNvbG9yQnJld2VyKQ0KbGlicmFyeShzZXFpbnIpDQpsaWJyYXJ5KHN0cmluZ3IpDQpsaWJyYXJ5KEV4cGxvcmVNb2RlbE1hdHJpeCkNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmBgYA0KDQoNCg0KIyBJbXBvcnQgZGF0YQ0KDQoNCmBgYHtyfQ0KZGYgPC0gcmVhZC5jc3YoImV2aWRlbmNlLnR4dCIsaGVhZGVyPVRSVUUsIHNlcCA9ICIsIikNCiNJIGNhbiBpZ25vcmUgdGhlIHNpZ21hIHByb3RlaW5zICh0aG9zZSB3ZXJlIGp1c3QgdXNlZCBmb3IgUUMgcHVycG9zZXMpDQpkZiA8LSBkZiAlPiUgZmlsdGVyKCFncmVwbCgiU2lnbWEiLCBkZiRQcm90ZWlucykpDQojZmlsdGVyIG91dCBwaG9zcGhvIHNpdGVzIHdpdGggbGVzcyB0aGFuIDc1JSBwcm9iYWJpbGl0eQ0KIyhvdGhlciBmaWx0ZXJpbmcgb3B0aW9ucyBhcmUgcG9zc2libGUpDQpmaWx0ZXJfcm93cyA8LSBzYXBwbHkoZGYkUGhvc3Boby4uU1RZLi5Qcm9iYWJpbGl0aWVzLCBmdW5jdGlvbih4KXsNCiAgaWYgKCF4PT0iIil7DQogICAgcHJvYiA8LSBzdHJfZXh0cmFjdF9hbGwoeCwgICIoPzw9XFwoKS4rPyg/PVxcKSkiKVtbMV1dDQogICAgaWYgKCFhbnkoYXMuZG91YmxlKHByb2IpID4gMC43NSkpe3JldHVybih3aGljaChkZiRQaG9zcGhvLi5TVFkuLlByb2JhYmlsaXRpZXMgPT0geCkpfQ0KICB9DQp9LCBVU0UuTkFNRVMgPSBGKQ0KZmlsdGVyX3Jvd3MgPC0gdW5pcXVlKHVubGlzdChmaWx0ZXJfcm93cykpDQpucm93KGRmKQ0KZGYgPC0gZGZbLWZpbHRlcl9yb3dzLF0NCm5yb3coZGYpDQojTm93IGdldCBmb3JtYXQgaW50byB3aWRlIGZvcm1hdA0KZGZfd2lkZSA8LSBwaXZvdF93aWRlcihkZiwgaWRfY29scyA9IGMoIlNlcXVlbmNlIiwgIk1vZGlmaWNhdGlvbnMiLCAiTW9kaWZpZWQuc2VxdWVuY2UiLCAiUHJvdGVpbnMiLCAiTGVhZGluZy5wcm90ZWlucyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJldmVyc2UiLCAiUG90ZW50aWFsLmNvbnRhbWluYW50IiwgIlByb3RlaW4uZ3JvdXAuSURzIiwgIkxlYWRpbmcucmF6b3IucHJvdGVpbiIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjSXMgZGF0IGhpZXIgZGUgYmVzdGUgbWFuaWVyIG9tIG1ldCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI2dlZHVwbGljZWVyZGUgZmVhdHVyZXMgb20gdGUgZ2Fhbj8NCiAgICAgICAgICAgICAgICAgICAgICAgbmFtZXNfZnJvbSA9ICJSYXcuZmlsZSIsIG5hbWVzX3ByZWZpeCA9ICJJbnRlbnNpdHlfIiwgdmFsdWVzX2Zyb20gPSAiSW50ZW5zaXR5IiwgdmFsdWVzX2ZuID0gbWF4KQ0KYGBgDQoNCg0KYGBge3J9DQplY29scyA8LSBncmVwKCJJbnRlbnNpdHkiLGNvbG5hbWVzKGRmX3dpZGUpKQ0KI29yZGVyIGRhdGFmcmFtZSBieSBwcm90ZWluLCBmb3IgdGhlIG5vcm1hbGlzYXRpb24gc3RlcA0KZGZfd2lkZSA9IGRmX3dpZGVbb3JkZXIoZGZfd2lkZSRMZWFkaW5nLnJhem9yLnByb3RlaW4pLF0NCnBlIDwtIHJlYWRRRmVhdHVyZXMoZGZfd2lkZSxlY29sPSBlY29scyxuYW1lPSJwZXB0aWRvZm9ybVJhdyIpDQpgYGANCg0KYGBge3J9DQpyb3duYW1lcyhwZVtbInBlcHRpZG9mb3JtUmF3Il1dKSA8LSByb3dEYXRhKHBlW1sicGVwdGlkb2Zvcm1SYXciXV0pJE1vZGlmaWVkLnNlcXVlbmNlDQpgYGANCg0KIyMgRXhwZXJpbWVudGFsIExheW91dA0KDQpgYGB7cn0NCm1ldGFkYXRhIDwtIHJlYWQuY3N2KCJFeHBlcmltZW50YWwgRGVzaWduLmNzdiIpDQpgYGANCg0KYGBge3J9DQpjb2xEYXRhKHBlKSRmaWxlIDwtIHNhcHBseShzdHJfc3BsaXQocm93bmFtZXMoY29sRGF0YShwZSkpLCAiXyIpLCBmdW5jdGlvbih4KSB4W1syXV0pDQptZXRhZGF0YSRGaWxlIDwtIHN1Yih4PW1ldGFkYXRhJEZpbGUsIHBhdHRlcm49Ii5yYXciLHJlcGxhY2VtZW50ID0gIiIpDQpjb2xEYXRhKHBlKSRjb25kaXRpb24gPC0gc2FwcGx5KGNvbERhdGEocGUpJGZpbGUsIGZ1bmN0aW9uKHgpew0KICBtZXRhZGF0YVttZXRhZGF0YSRGaWxlPT14LF0kQ29uZGl0aW9uDQp9LCBVU0UuTkFNRVMgPSBGKQ0KY29sRGF0YShwZSkkc3Vic2V0IDwtIHNhcHBseShjb2xEYXRhKHBlKSRmaWxlLCBmdW5jdGlvbih4KXsNCiAgbWV0YWRhdGFbbWV0YWRhdGEkRmlsZT09eCxdJFN1YnNldA0KfSwgVVNFLk5BTUVTID0gRikNCmNvbERhdGEocGUpJGNvbmRpdGlvbiA8LSBjYXNlX3doZW4oZ3JlcGwoIkEiLCBjb2xEYXRhKHBlKSRjb25kaXRpb24pIH4gIkEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiQiIpDQpjb2xEYXRhKHBlKQ0KYGBgDQoNCg0KYGBge3J9DQpNU25iYXNlOjpwbG90TkEoYXNzYXkocGVbWyJwZXB0aWRvZm9ybVJhdyJdXSkpICsNCiAgeGxhYigiUGVwdGlkZSBpbmRleCAob3JkZXJlZCBieSBkYXRhIGNvbXBsZXRlbmVzcykiKQ0KYGBgDQoNCg0KIyBQcmVwcm9jZXNzaW5nDQoNCg0KYGBge3J9DQpyb3dEYXRhKHBlW1sicGVwdGlkb2Zvcm1SYXciXV0pJG5Ob25aZXJvIDwtIHJvd1N1bXMoYXNzYXkocGVbWyJwZXB0aWRvZm9ybVJhdyJdXSkgPiAwLCBuYS5ybSA9IFQpDQpwZSA8LSB6ZXJvSXNOQShwZSwgaSA9ICJwZXB0aWRvZm9ybVJhdyIpDQpwZSA8LSBmaWx0ZXJGZWF0dXJlcyhwZSwgflJldmVyc2UgIT0gIisiKQ0KcGUgPC0gZmlsdGVyRmVhdHVyZXMocGUsIH5Qb3RlbnRpYWwuY29udGFtaW5hbnQgIT0gIisiKQ0KcGUgPC0gbG9nVHJhbnNmb3JtKHBlLCBiYXNlID0gMiwgaSA9ICJwZXB0aWRvZm9ybVJhdyIsIG5hbWUgPSAicGVwdGlkb2Zvcm1Mb2ciKQ0KcGUgPC0gcGVbcm93RGF0YShwZVtbInBlcHRpZG9mb3JtUmF3Il1dKSRuTm9uWmVybz4yLCxdDQpwZSA8LSBRRmVhdHVyZXM6Om5vcm1hbGl6ZShwZSwgbWV0aG9kID0gImNlbnRlci5tZWRpYW4iLCBpID0gInBlcHRpZG9mb3JtTG9nIiwgbmFtZSA9ICJwZXB0aWRvZm9ybSIpDQpjb2xEYXRhKHBlW1sicGVwdGlkb2Zvcm0iXV0pIDwtIGNvbERhdGEocGUpDQpgYGANCg0KDQojIyBOb3JtYWxpc2F0aW9uIHZpYSByb2J1c3Qgc3VtbWFyaXNhdGlvbg0KDQoNCmBgYHtyLHdhcm5pbmc9RkFMU0V9DQpwZSA8LSBhZ2dyZWdhdGVGZWF0dXJlcyhwZSwNCiBpID0gInBlcHRpZG9mb3JtIiwNCiBmY29sID0gIkxlYWRpbmcucmF6b3IucHJvdGVpbiIsDQogbmEucm0gPSBUUlVFLA0KIG5hbWUgPSAicHJvdGVpblJvYnVzdCIsDQogZnVuID0gTXNDb3JlVXRpbHM6OnJvYnVzdFN1bW1hcnkpDQpgYGANCg0KYGBge3J9DQojT25seSB0YWtlIHBlcGZvcm1zIHRoYXQgaGF2ZSBhIHBhcmVudCBwcm90ZWluDQojKHdoZW4gdGhlcmUgaXMgbm8gZ2xvYmFsIHByb2ZpbGluZyBkYXRhc2V0LCB0aGlzIHdpbGwgYmUgYWxsIHBlcHRpZG9mb3JtcykNCnBlcFdpdGhQcm90ZWluIDwtIHJvd0RhdGEocGVbWyJwZXB0aWRvZm9ybSJdXSkkUHJvdGVpbnMgJWluJSByb3duYW1lcyhwZVtbInByb3RlaW5Sb2J1c3QiXV0pDQpwZVBlcFdpdGhQcm90ZWluICA8LSBwZVtbInBlcHRpZG9mb3JtIl1dW3BlcFdpdGhQcm90ZWluLF0NCnBlIDwtIGFkZEFzc2F5KHBlLHBlUGVwV2l0aFByb3RlaW4sInBlcGZvcm1SZWwiKQ0KI25vcm1hbGlzYXRpb24gZm9yIHByb3RlaW4gYWJ1bmRhbmNlIHN0ZXANCmFzc2F5KHBlW1sicGVwZm9ybVJlbCJdXSkgPC0gYXNzYXkocGVbWyJwZXBmb3JtUmVsIl1dKSAtIGFzc2F5KHBlW1sicHJvdGVpblJvYnVzdCJdXSlbcm93RGF0YShwZVtbInBlcGZvcm1SZWwiXV0pJFByb3RlaW5zLGNvbG5hbWVzKGFzc2F5KHBlW1sicGVwZm9ybVJlbCJdXSkpXQ0KYm94cGxvdChhc3NheShwZVtbInBlcGZvcm1SZWwiXV0pKQ0KYGBgDQoNCg0KIyBEaWZmZXJlbnRpYWwgcGVwdGlkb2Zvcm0gdXNhZ2UgKERQRlUpDQoNCiMjIEh5cG90aGVzaXN0ZXN0IGZvciBlYWNoIGNvbnRyYXN0DQoNCmBgYHtyfQ0KY29sRGF0YShwZSkkY29uZGl0aW9uIDwtIHJlbGV2ZWwoYXMuZmFjdG9yKGNvbERhdGEocGUpJGNvbmRpdGlvbiksIHJlZiA9ICJCIikNCmNvbERhdGEocGUpJHN1YnNldCA8LSBhcy5mYWN0b3IoY29sRGF0YShwZSkkc3Vic2V0KQ0KYGBgDQoNCmBgYHtyfQ0KcGUgPC0gbXNxcm9iMjo6bXNxcm9iKG9iamVjdCA9IHBlLCBpID0gInBlcGZvcm1SZWwiLCBmb3JtdWxhID0gfmNvbmRpdGlvbipzdWJzZXQsIHJvYnVzdD1GQUxTRSkNCnJvd0RhdGEocGVbWyJwZXBmb3JtUmVsIl1dKSRtc3Fyb2JNb2RlbHNbWzJdXSAlPiUNCiAgICAgICAgICAgICAgICAgIGdldENvZWYNCmBgYA0KDQoNCmBgYHtyfQ0KZnJhY3Rpb25fb2ZfeXMgPC0gKGNvbERhdGEocGUpICU+JSBhc190aWJibGUoKSAlPiUgZmlsdGVyKHN1YnNldCA9PSAieSIpICU+JSBucm93KCkpIC8gbnJvdyhjb2xEYXRhKHBlKSkNCmNvbnRyYXN0cyA8LSBjKCJjb25kaXRpb25BIiwgImNvbmRpdGlvbkEgKyBjb25kaXRpb25BOnN1YnNldHkiLCAiY29uZGl0aW9uQTpzdWJzZXR5IiwgImNvbmRpdGlvbkEgKyAwLjUgKiBjb25kaXRpb25BOnN1YnNldHkiLCAiY29uZGl0aW9uQSArIDAuNjY2NjY2NyAqIGNvbmRpdGlvbkE6c3Vic2V0eSIpDQpMIDwtIG1ha2VDb250cmFzdChjKCJjb25kaXRpb25BID0gMCIsDQogICAgICAgICAgICAgICAgICAgICJjb25kaXRpb25BICsgY29uZGl0aW9uQTpzdWJzZXR5ID0gMCIsDQogICAgICAgICAgICAgICAgICAgICJjb25kaXRpb25BOnN1YnNldHkgPSAwIiwNCiAgICAgICAgICAgICAgICAgICAgImNvbmRpdGlvbkEgKyAwLjUgKiBjb25kaXRpb25BOnN1YnNldHkgPSAwIiwNCiAgICAgICAgICAgICAgICAgICAgImNvbmRpdGlvbkEgKyAwLjY2NjY2NjcgKiBjb25kaXRpb25BOnN1YnNldHkgPSAwIiksDQogICAgICAgICAgICAgICAgICBwYXJhbWV0ZXJOYW1lcyA9IHJvd0RhdGEocGVbWyJwZXBmb3JtUmVsIl1dKSRtc3Fyb2JNb2RlbHNbWzJdXSAlPiUNCiAgICAgICAgICAgICAgICAgIGdldENvZWYgJT4lDQogICAgICAgICAgICAgICAgICBuYW1lcykNCnBlIDwtIGh5cG90aGVzaXNUZXN0KG9iamVjdCA9IHBlLCBpID0gInBlcGZvcm1SZWwiLCBjb250cmFzdCA9IEwsIG92ZXJ3cml0ZSA9IFQpDQpgYGANCg0KDQojIyMgVm9sY2Fub3Bsb3QgDQoNCmBgYHtyfQ0Kdm9sY2FubyA8LSBsaXN0KCkNCmZvciAoY29udHJhc3QgaW4gY29udHJhc3RzKXsNCnZvbGNhbm9bW2NvbnRyYXN0XV0gPC0gcm93RGF0YShwZVtbInBlcGZvcm1SZWwiXV0pW1tjb250cmFzdF1dJT4lDQogICAgICAgICAgICBnZ3Bsb3QoYWVzKHggPSBsb2dGQywgeSA9IC1sb2cxMChwdmFsKSwgDQogICAgICAgICAgICAgICAgICAgY29sb3IgPSBhZGpQdmFsIDwgMC4wNSwNCiAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uPXJvd0RhdGEocGVbWyJwZXBmb3JtUmVsIl1dKVssM10pKSArDQogIGdlb21fcG9pbnQoY2V4ID0gMi41KSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBhbHBoYShjKCJibGFjayIsICJyZWQiKSwgMC41KSkgKyANCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgeWxhYigiLWxvZzEwKHB2YWx1ZSkiKSArDQogIGdndGl0bGUoY29udHJhc3QpDQp9DQp2b2xjYW5vDQpgYGANCg0KYGBge3IgZXZhbD1GQUxTRSwgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MTIsIGluY2x1ZGU9RkFMU0V9DQpmb3IoY29udHJhc3QgaW4gY29udHJhc3RzKXsNCnNpZ05hbWVzIDwtIHJvd0RhdGEocGVbWyJwZXBmb3JtUmVsIl1dKVtbY29udHJhc3RdXSAlPiUNCiByb3duYW1lc190b19jb2x1bW4oInBlcHRpZG9mb3JtIikgJT4lDQogZmlsdGVyKGFkalB2YWw8MC4wNSkgJT4lDQogcHVsbChwZXB0aWRvZm9ybSkNCmhlYXRtYXAoYXNzYXkocGVbWyJwZXBmb3JtUmVsIl1dKVtzaWdOYW1lcywgXSwgbWFpbiA9IGNvbnRyYXN0KQ0KfQ0KYGBgDQoNCiMjIyBTaWduaWZpY2FudCBwZXB0aWRvZm9ybXMgZm9yIGVhY2ggY29udHJhc3QNCg0KDQpgYGB7cn0NCnRhYmxlcyA8LSBsaXN0KCkNCmZvciAoY29udHJhc3QgaW4gY29udHJhc3RzKXsNCnNpZ1RhYmxlIDwtIHJvd0RhdGEocGVbWyJwZXBmb3JtUmVsIl1dKVtbY29udHJhc3RdXQ0KaWYobnJvdyhzaWdUYWJsZSAlPiUNCiAgbmEuZXhjbHVkZSAlPiUNCiAgZmlsdGVyKGFkalB2YWw8MC4wNSkpPjApew0Kc2lnVGFibGUgPC0gc2lnVGFibGUgJT4lDQogIG5hLmV4Y2x1ZGUgJT4lDQogIGZpbHRlcihhZGpQdmFsPDAuMDUpICU+JQ0KICBhcnJhbmdlKHB2YWwpICU+JQ0KICBtdXRhdGUoDQogICAgc2UgPSBmb3JtYXQoc2UsIGRpZ2l0cyA9IDIpLCANCiAgICBkZiA9IGZvcm1hdChkZiwgZGlnaXRzID0yKSwNCiAgICB0ID0gZm9ybWF0KHQsIGRpZ2l0cyA9IDIpLA0KICAgIGFkalB2YWwgPSBmb3JtYXQoYWRqUHZhbCwgZGlnaXRzID0gMyksDQogICAgcmFuayA9IDE6bGVuZ3RoKGxvZ0ZDKSANCiAgKSANCnNpZ1RhYmxlX3ByaW50IDwtIHNpZ1RhYmxlICU+JSBtdXRhdGUocGVwdGlkb2Zvcm0gPSByb3duYW1lcyhzaWdUYWJsZSkpICU+JSBndCgpICU+JSB0YWJfaGVhZGVyKHRpdGxlID0gbWQoY29udHJhc3QpKQ0KdGFibGVzW1tjb250cmFzdF1dIDwtIHNpZ1RhYmxlDQp9DQp9DQprbml0cjo6a2FibGUodGFibGVzKQ0KYGBgDQoNCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9DQp0YWJsZXNfdG9Dc3YgPC0gZG8uY2FsbCgicmJpbmQiLCB0YWJsZXMpDQp0YWJsZXNfdG9Dc3YgPC0gdGFibGVzX3RvQ3N2ICU+JSByb3duYW1lc190b19jb2x1bW4oImNvbnRyYXN0IikNCnBlcGZvcm1zIDwtIHNhcHBseSh1bmlxdWUodGFibGVzX3RvQ3N2JGNvbnRyYXN0KSwgZnVuY3Rpb24oeCl7cm93bmFtZXModGFibGVzW1t4XV0pfSwgVVNFLk5BTUVTID0gRikNCnRhYmxlc190b0NzdiRQZXB0aWRvZm9ybSA8LSBwZXBmb3Jtcw0Kd3JpdGUuY3N2KHRhYmxlc190b0NzdiwgZmlsZSA9ICJDOi9Vc2Vycy9OaW5hL09uZURyaXZlIC0gVUdlbnQvRG9jdW1lbnRlbi9Eb2N0b3JhYXQvbXNxcm9iUFRNL1Bob3NwaG9EYXRhc2V0IC9zaWduaWZpY2FuY2VfdGFibGVzX3BlcHRpZG9mb3JtLmNzdiIpDQpgYGANCg0KDQojIERQVE0NCg0KIyMgcHRtIHN1bW1hcmlzYXRpZQ0KDQojIyMgRGV0ZXJtaW5lIGxvY2F0aW9uIG9mIHB0bQ0KDQpgYGB7cn0NCmZhc3RhIDwtICJodW1hbi5mYXN0YSINCnBhcnNlZF9mYXN0YSA8LSByZWFkLmZhc3RhKGZpbGUgPSBmYXN0YSwgc2VxdHlwZSA9ICJBQSIsIGFzLnN0cmluZyA9IFQpDQpgYGANCg0KICANCmBgYHtyfQ0KI21vZGlmaWVkIHNlcXVlbmNlIGNvbHVtbiBjb250YWlucyBfIHRoYXQgZG9lcyBub3QgbWF0dGVyLCBidXQgaGluZGVycyBsb2NhdGlvbiBkZXRlcm1pbmluZw0Kcm93RGF0YShwZVtbInBlcGZvcm1SZWwiXV0pJG1vZGlmaWVkX3NlcXVlbmNlIDwtIGdzdWIoIl8iLCAiIiwgcm93RGF0YShwZVtbInBlcGZvcm1SZWwiXV0pJE1vZGlmaWVkLnNlcXVlbmNlKQ0KYGBgDQoNCiAgDQoNCmBgYHtyfQ0KZ2V0X3B0bV9sb2NhdGlvbiA8LSBmdW5jdGlvbihmZWF0dXJlLCBkYXRhLCBmYXN0YSwgbW9kX2NvbHVtbiA9ICJNb2RpZmljYXRpb25zIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlcHRpZGVfc2VxX2NvbHVtbiA9ICJTZXF1ZW5jZSIsIG1vZF9zZXFfY29sdW1uID0gIm1vZGlmaWVkX3NlcXVlbmNlIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3RlaW5fY29sdW1uID0gIkxlYWRpbmcucmF6b3IucHJvdGVpbiIsIHNwbGl0ID0gIiwiLCBjb2xsYXBzZSA9ICIsICIpew0KICBwcm90IDwtIGRhdGFbZmVhdHVyZSxdW1twcm90ZWluX2NvbHVtbl1dDQogIHBlcF9zZXEgPC0gZGF0YVtmZWF0dXJlLF1bW3BlcHRpZGVfc2VxX2NvbHVtbl1dDQogIG1vZF9zZXEgPC0gZGF0YVtmZWF0dXJlLF1bW21vZF9zZXFfY29sdW1uXV0NCiAgcHJvdF9zZXEgPC0gZmFzdGFbW3Byb3RdXVsxXQ0KDQogICNmaW5kIGxvY2F0aW9uIG9mIHBlcHRpZGUgaW4gcHJvdGVpbg0KICAjYWRkIC0xIGhlcmUsIHNvIHRoYXQgdGhlIGFkZGl0aW9uIG9mIHRoZSBsb2NhdGlvbiBsYXRlciBvbiBpcyBjb3JyZWN0DQogIHBlcF9sb2NhdGlvbiA8LSB1bmxpc3QobGFwcGx5KGdyZWdleHByKHBhdHRlcm4gPSBwZXBfc2VxLCBwcm90X3NlcSksIG1pbikpIC0gMQ0KICBmaW5hbF9tb2QgPC0gYygpDQogIGogPC0gbW9kX3NlcQ0KICAjZ28gb3ZlciB0aGUgbW9kaWZpY2F0aW9ucyBpbnNpZGUgdGhlIG1vZGlmaWVkIHNlcXVlbmNlDQogIGZvcihtb2QgaW4gcmVnbWF0Y2hlcyhtb2Rfc2VxLCBncmVnZXhwcigiXFwoLio/XFwpXFwpIiwgbW9kX3NlcSwgcGVybD1UKSlbWzFdXSl7DQogICAgI2ZpbmQgbG9jYXRpb24gb2YgbW9kaWZpY2F0aW9uIGluIHBlcHRpZGUNCiAgICBtb2RfbG9jYXRpb24gPC0gdW5saXN0KGxhcHBseShncmVnZXhwcihwYXR0ZXJuID0gbW9kLCBqLCBmaXhlZCA9IFQpLCBtaW4pKQ0KICAgICNnZXQgbG9jYXRpb24gaW4gcHJvdGVpbiAoLTEgYmVjYXVzZSBlbHNlIGl0IGdpdmVzIHlvdSB0aGUgbG9jYXRpb24gYWZ0ZXIgYmVjYXVzZSBvZiB0aGUgcHJlc2VuY2Ugb2YgdGhlIG1vZGlmaWNhdGlvbiBpbiB0aGUgc3RyaW5nKQ0KICAgIGxvY2F0aW9uIDwtIG1vZF9sb2NhdGlvbiArIHBlcF9sb2NhdGlvbiAtMQ0KICAgICNhZGQgbG9jYXRpb24gdG8gbW9kaWZpY2F0aW9uDQogICAgbW9kXyA8LSBwYXN0ZShtb2QsIGxvY2F0aW9uKQ0KICAgICNzYXZlIG1vZGlmaWNhdGlvbg0KICAgIGZpbmFsX21vZCA8LSBjKGZpbmFsX21vZCwgbW9kXykNCiAgICAjbm93IHJlbW92ZSBjdXJyZW50IG1vZGlmaWNhdGlvbiBmcm9tIHRoZSBzZXF1ZW5jZSwgc28gdGhhdCB3ZSBjYW4gY29udGludWUgdG8gdGhlIG5leHQgbW9kDQogICAgc3RyX3N1YihqLCBtb2RfbG9jYXRpb24sIG5jaGFyKG1vZCkrbW9kX2xvY2F0aW9uLTEpIDwtICIiDQogIH0NCiAgcmV0dXJuKHBhc3RlKGZpbmFsX21vZCwgY29sbGFwc2UgPSBjb2xsYXBzZSkpDQp9DQpgYGANCg0KYGBge3J9DQpyb3dEYXRhKHBlW1sicGVwZm9ybVJlbCJdXSkkbW9kIDwtIHNhcHBseShyb3duYW1lcyhyb3dEYXRhKHBlW1sicGVwZm9ybVJlbCJdXSkpLCBmdW5jdGlvbih4KXsNCiAgICBnZXRfcHRtX2xvY2F0aW9uKHgsIHJvd0RhdGEocGVbWyJwZXBmb3JtUmVsIl1dKSwgcGFyc2VkX2Zhc3RhKQ0KfSwgVVNFLk5BTUVTID0gRikNCmBgYA0KDQoNCmBgYHtyfQ0KI0FkZCBwdG0gdmFyaWFibGUgPSBwcm90ZWluICsgbW9kaWZpY2F0aW9uDQpyb3dEYXRhKHBlW1sicGVwZm9ybVJlbCJdXSkkcHRtIDwtIGlmZWxzZShyb3dEYXRhKHBlW1sicGVwZm9ybVJlbCJdXSkkbW9kICE9ICIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZShyb3dEYXRhKHBlW1sicGVwZm9ybVJlbCJdXSkkTGVhZGluZy5yYXpvci5wcm90ZWluLCByb3dEYXRhKHBlW1sicGVwZm9ybVJlbCJdXSkkbW9kLCBzZXA9Il8iKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIiKQ0KYGBgDQoNCiMjIyBHZXQgcHRtIGxldmVsIGludGVuc2l0eSBtYXRyaXgNCg0KR2V0IGFsbCB1bmlxdWUgcHRtcyBwcmVzZW50IGluIHRoZSBkYXRhc2V0IChhbGwgcHJvdGVpbiAtIG1vZGlmaWNhdGlvbiAtIGxvY2F0aW9uIGNvbWJpbmF0aW9ucykNCg0KYGBge3J9DQpwcm90cyA8LSB1bmlxdWUocm93RGF0YShwZVtbInBlcGZvcm1SZWwiXV0pJExlYWRpbmcucmF6b3IucHJvdGVpbikNCiNEbyBmb3IgZWFjaCBwcm90ZWluDQpwdG1zIDwtIHNhcHBseShwcm90cywgZnVuY3Rpb24oaSkgew0KICBwZV9zdWIgPC0gcGVbWyJwZXBmb3JtUmVsIl1dW2dyZXBsKGksIHJvd0RhdGEocGVbWyJwZXBmb3JtUmVsIl1dKSRMZWFkaW5nLnJhem9yLnByb3RlaW4sIGZpeGVkID0gVCksXQ0KICAjcGVfc3ViIDwtIGZpbHRlckZlYXR1cmVzKHBlLH5ncmVwbChMZWFkaW5nLnJhem9yLnByb3RlaW4scGF0dGVybj1pLGZpeGVkID0gVCkpDQogICNHZXQgYWxsIHVuaXF1ZSBtb2RpZmljYXRpb24gcHJlc2VudCBvbiB0aGF0IHByb3RlaW4NCiAgbW9kcyA8LSB1bmlxdWUodW5saXN0KHN0cnNwbGl0KHJvd0RhdGEocGVfc3ViKSRtb2QsIHNwbGl0ID0gIiwgIiwgZml4ZWQgPSBUUlVFKSkpDQogICNBZGQgcHJvdGVpbiBpbmZvIHRvIG1vZHMNCiAgcHRtIDwtIHBhc3RlKHJlcChpLCBsZW5ndGgobW9kcykpLCBtb2RzKQ0KICAjcmV0dXJuIGFsbCB0aGUgcHJvdGVpbi1tb2RzIGNvbWJpbmF0aW9ucw0KICBwdG0NCn0pDQpwdG1zIDwtIGFzLnZlY3Rvcih1bmxpc3QocHRtcykpDQpgYGANCg0KDQoNCmBgYHtyfQ0KI0ZvciBlYWNoIHB0bSBkbw0KcHRtX3hfYXNzYXkgPC0gc2FwcGx5KHNlcSgxOmxlbmd0aChwdG1zKSksIGZ1bmN0aW9uKGkpeyANCiAgeCA8LSBwdG1zW2ldDQogICNHZXQgY3VycmVudCBwcm90ZWluIGFuZCBtb2QgZnJvbSBwdG0NCiAgcHJvdCA8LSBzdHJfc3BsaXQoeCwgIiAiLCAyKVtbMV1dWzFdDQogIGN1cnJlbnRfcHRtIDwtIHN0cl9zcGxpdCh4LCAiICIsIDIpW1sxXV1bMl0NCiAgI2ZpbHRlciBvbiB0aGF0IHByb3RlaW4gYW5kIG9uIHRoYXQgbW9kIHRvIG9idGFpbiBhbGwgcGVwdGlkb2Zvcm1zIHRoYXQgY29ycmVzcG9uZCB0byB0aGUgcHRtDQogIHBlX3N1YiA8LSBwZVtbInBlcGZvcm1SZWwiXV1bZ3JlcGwocHJvdCwgcm93RGF0YShwZVtbInBlcGZvcm1SZWwiXV0pJExlYWRpbmcucmF6b3IucHJvdGVpbiwgZml4ZWQgPSBUKSxdDQogICNwZV9zdWIgPC0gZmlsdGVyRmVhdHVyZXMocGUsfmdyZXBsKExlYWRpbmcucmF6b3IucHJvdGVpbixwYXR0ZXJuPXByb3QsIGZpeGVkID0gVCkpDQogIHB0bV9zdWIgPC0gcGVfc3ViW2dyZXBsKGN1cnJlbnRfcHRtLCByb3dEYXRhKHBlX3N1YikkbW9kLCBmaXhlZCA9IFQpLF0NCiAgI3B0bV9zdWIgPC0gZmlsdGVyRmVhdHVyZXMocGVfc3ViLH5ncmVwbChtb2QscGF0dGVybj1jdXJyZW50X3B0bSwgZml4ZWQ9VCkpW1sicGVwdGlkb2Zvcm1Ob3JtIl1dDQogICNHZXQgaW50ZW5zaXR5IHZhbHVlcyBvZiB0aG9zZSBwZXB0aWRvZm9ybXMNCiAgeSA8LSBhc3NheShwdG1fc3ViKQ0KICAjQW5kIHN1bW1hcmlzZSB0aGVtIHRvIDEgcm93IG9mIGludGVuc2l0eSB2YWx1ZXM6IDEgdmFsdWUgcGVyIHNhbXBsZSBmb3IgdGhhdCBwdG0NCiAgcHRtX3kgPC0gdHJ5KE1zQ29yZVV0aWxzOjpyb2J1c3RTdW1tYXJ5KHkpLCBzaWxlbnQgPSBUKQ0KICBpZiAoaXMocHRtX3ksICJ0cnktZXJyb3IiKSl7DQogICAgcHRtX3kgPC0gcmVwKE5BLCBuY29sKHkpKX0NCiAgcHRtX3kNCn0pDQojVGhlbiB3ZSBnZXQgdGhlIGludGVuc2l0eSBhc3NheSBvbiBwdG0gbGV2ZWwNCnB0bV94X2Fzc2F5IDwtIHQocHRtX3hfYXNzYXkpDQpyb3duYW1lcyhwdG1feF9hc3NheSkgPC0gcHRtcw0KYGBgDQoNCiMjIyBBZGQgdG8gUUZlYXR1cmVzIG9iamVjdA0KDQpGaWx0ZXIgb3V0IHB0bXMgd2l0aCBhbGwgemVybyBpbnRlbnNpdGllcw0KDQpgYGB7cn0NCnByaW50KHBhc3RlKG5yb3cocHRtX3hfYXNzYXkpLCAicHRtcyBiZWZvcmUgZmlsdGVyaW5nIikpDQpmaWx0ZXJpbmcgPC0gcm93U3VtcyhwdG1feF9hc3NheSAhPSAwLCBuYS5ybT1UUlVFKSA+IDAgDQpwdG1feF9hc3NheSA8LSBwdG1feF9hc3NheVtmaWx0ZXJpbmcsXQ0KcHJpbnQocGFzdGUobnJvdyhwdG1feF9hc3NheSksICJwdG1zIGFmdGVyIGZpbHRlcmluZyIpKQ0KYGBgDQoNCmBgYHtyfQ0KYWxsKHJvd25hbWVzKGNvbERhdGEocGUpKSA9PSBjb2xuYW1lcyhwdG1feF9hc3NheSkpDQpyb3dkYXRhIDwtIGRhdGEuZnJhbWUocHRtID0gcm93bmFtZXMocHRtX3hfYXNzYXkpKQ0Kcm93ZGF0YSRwcm90ZWluIDwtIHNhcHBseShzdHJfc3BsaXQocm93ZGF0YSRwdG0sIHBhdHRlcm49IiAiKSxmdW5jdGlvbih4KSB4WzFdKQ0KcHRtX3lfYXNzYXkgPC0gU3VtbWFyaXplZEV4cGVyaW1lbnQoYXNzYXlzPWFzLm1hdHJpeChwdG1feF9hc3NheSksIHJvd0RhdGE9cm93ZGF0YSwgY29sRGF0YT1jb2xEYXRhKHBlKSkNCmBgYA0KDQoNCmBgYHtyfQ0KcGUgPC0gYWRkQXNzYXkocGUsIHB0bV95X2Fzc2F5LCAicHRtUmVsIikNCmBgYA0KDQoNCg0KIyMgSHlwb3RoZXNpc3Rlc3QgZm9yIGVhY2ggY29udHJhc3QNCg0KDQpgYGB7cn0NCnBlIDwtIG1zcXJvYjI6Om1zcXJvYihvYmplY3QgPSBwZSwgaSA9ICJwdG1SZWwiLCBmb3JtdWxhID0gfmNvbmRpdGlvbipzdWJzZXQsIHJvYnVzdD1UUlVFLCBvdmVyd3JpdGUgPSBUKQ0Kcm93RGF0YShwZVtbInB0bVJlbCJdXSkkbXNxcm9iTW9kZWxzW1syXV0gJT4lDQogICAgICAgICAgICAgICAgICBnZXRDb2VmDQpgYGANCg0KDQoNCmBgYHtyfQ0KY29udHJhc3RzIDwtIGMoImNvbmRpdGlvbkEiLCAiY29uZGl0aW9uQSArIGNvbmRpdGlvbkE6c3Vic2V0eSIsICJjb25kaXRpb25BOnN1YnNldHkiLCAiY29uZGl0aW9uQSArIDAuNSAqIGNvbmRpdGlvbkE6c3Vic2V0eSIsICJjb25kaXRpb25BICsgMC42NjY2NjY3ICogY29uZGl0aW9uQTpzdWJzZXR5IikNCkwgPC0gbWFrZUNvbnRyYXN0KGMoImNvbmRpdGlvbkEgPSAwIiwNCiAgICAgICAgICAgICAgICAgICAgImNvbmRpdGlvbkEgKyBjb25kaXRpb25BOnN1YnNldHkgPSAwIiwNCiAgICAgICAgICAgICAgICAgICAgImNvbmRpdGlvbkE6c3Vic2V0eSA9IDAiLA0KICAgICAgICAgICAgICAgICAgICAiY29uZGl0aW9uQSArIDAuNSAqIGNvbmRpdGlvbkE6c3Vic2V0eSA9IDAiLA0KICAgICAgICAgICAgICAgICAgICAiY29uZGl0aW9uQSArIDAuNjY2NjY2NyAqIGNvbmRpdGlvbkE6c3Vic2V0eSA9IDAiKSwgICANCiAgICAgICAgICAgICAgICAgIHBhcmFtZXRlck5hbWVzID0gcm93RGF0YShwZVtbInB0bVJlbCJdXSkkbXNxcm9iTW9kZWxzW1syXV0gJT4lDQogICAgICAgICAgICAgICAgICBnZXRDb2VmICU+JQ0KICAgICAgICAgICAgICAgICAgbmFtZXMpDQpwZSA8LSBoeXBvdGhlc2lzVGVzdChvYmplY3QgPSBwZSwgaSA9ICJwdG1SZWwiLCBjb250cmFzdCA9IEwsIG92ZXJ3cml0ZSA9IFQpDQpgYGANCg0KDQoNCiMjIyBWb2xjYW5vcGxvdCANCg0KDQpgYGB7cn0NCnZvbGNhbm9zIDwtIGxpc3QoKQ0KZm9yIChjb250cmFzdCBpbiBjb250cmFzdHMpew0KbGlicmFyeShwbG90bHkpDQp2b2xjYW5vc1tbY29udHJhc3RdXSA8LSANCiAgcm93RGF0YShwZVtbInB0bVJlbCJdXSlbW2NvbnRyYXN0XV0lPiUNCiAgZ2dwbG90KGFlcyh4ID0gbG9nRkMsIHkgPSAtbG9nMTAocHZhbCksIA0KICAgICAgICAgICAgIGNvbG9yID0gYWRqUHZhbCA8IDAuMDUsDQogICAgICAgICAgICAgYW5ub3RhdGlvbj1yb3dEYXRhKHBlW1sicHRtUmVsIl1dKVssM10pKSArDQogIGdlb21fcG9pbnQoY2V4ID0gMi41KSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBhbHBoYShjKCJibGFjayIsICJyZWQiKSwgMC41KSkgKyB0aGVtZV9taW5pbWFsKCkgKw0KICB5bGFiKCItbG9nMTAocHZhbHVlKSIpICsNCiAgZ2d0aXRsZShjb250cmFzdCkNCn0NCnZvbGNhbm9zDQpgYGANCg0KIyMjIEhlYXRtYXANCg0KV2UgZmlyc3Qgc2VsZWN0IHRoZSBuYW1lcyBvZiB0aGUgcHRtcyB0aGF0IHdlcmUgZGVjbGFyZWQgc2lnbmZpY2FudC4NCg0KYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0NCmZvcihjb250cmFzdCBpbiBjb250cmFzdHMpew0Kc2lnTmFtZXMgPC0gcm93RGF0YShwZVtbInB0bVJlbCJdXSlbW2NvbnRyYXN0XV0gJT4lDQogcm93bmFtZXNfdG9fY29sdW1uKCJwdG1SZWwiKSAlPiUNCiBmaWx0ZXIoYWRqUHZhbDwwLjA1KSAlPiUNCiBwdWxsKHB0bSkNCmhlYXRtYXAoYXNzYXkocGVbWyJwdG1SZWwiXV0pW3NpZ05hbWVzLCBdLCBtYWluID0gY29udHJhc3QpDQp9DQpgYGANCg0KDQojIyMgU2lnbmlmaWNhbnQgcHRtcyBmb3IgZWFjaCBjb250cmFzdA0KDQoNCmBgYHtyfQ0KdGFibGVzIDwtIGxpc3QoKQ0KZm9yIChjb250cmFzdCBpbiBjb250cmFzdHMpew0Kc2lnVGFibGUgPC0gcm93RGF0YShwZVtbInB0bVJlbCJdXSlbW2NvbnRyYXN0XV0NCmlmKG5yb3coc2lnVGFibGUgJT4lDQogIG5hLmV4Y2x1ZGUgJT4lDQogIGZpbHRlcihhZGpQdmFsPDAuMDUpKSA+IDApew0Kc2lnVGFibGUgPC0gc2lnVGFibGUgJT4lDQogIG5hLmV4Y2x1ZGUgJT4lDQogIGZpbHRlcihhZGpQdmFsPDAuMDUpICU+JQ0KICBhcnJhbmdlKHB2YWwpICU+JQ0KICBtdXRhdGUoDQogICAgc2UgPSBmb3JtYXQoc2UsIGRpZ2l0cyA9IDIpLCANCiAgICBkZiA9IGZvcm1hdChkZiwgZGlnaXRzID0yKSwNCiAgICB0ID0gZm9ybWF0KHQsIGRpZ2l0cyA9IDIpLA0KICAgIGFkalB2YWwgPSBmb3JtYXQoYWRqUHZhbCwgZGlnaXRzID0gMyksDQogICAgcmFuayA9IDE6bGVuZ3RoKGxvZ0ZDKSANCiAgKSANCnNpZ1RhYmxlX3ByaW50IDwtIHNpZ1RhYmxlICU+JSBtdXRhdGUocGVwdGlkb2Zvcm0gPSByb3duYW1lcyhzaWdUYWJsZSkpICU+JSBndCgpICU+JSB0YWJfaGVhZGVyKHRpdGxlID0gbWQoY29udHJhc3QpKQ0KdGFibGVzW1tjb250cmFzdF1dIDwtIHNpZ1RhYmxlDQp9DQp9DQprbml0cjo6a2FibGUodGFibGVzKQ0KYGBgDQoNCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9DQp0YWJsZXNfdG9Dc3YgPC0gZG8uY2FsbCgicmJpbmQiLCB0YWJsZXMpDQp0YWJsZXNfdG9Dc3YgPC0gdGFibGVzX3RvQ3N2ICU+JSByb3duYW1lc190b19jb2x1bW4oInJvd25hbWUiKQ0Kd3JpdGUuY3N2KHRhYmxlc190b0NzdiwgZmlsZSA9ICJzaWduaWZpY2FuY2VfdGFibGVzX1BUTS5jc3YiKQ0KYGBgDQoNCg0KYGBge3J9DQphID0gInNwfFExNjYxMHxFQ00xX0hVTUFOIChQaG9zcGhvIChTVFkpKSA4MCINCmIgPSAic3B8UDEzNjExfENTUEcyX0hVTUFOIChQaG9zcGhvIChTVFkpKSAyMTE1Ig0KdGFibGVzIDwtIGxpc3QoKQ0KZm9yIChjb250cmFzdCBpbiBjb250cmFzdHMpew0Kc2lnVGFibGUgPC0gcm93RGF0YShwZVtbInB0bVJlbCJdXSlbW2NvbnRyYXN0XV0NCnRhYmxlc1tbY29udHJhc3RdXSA8LSBzaWdUYWJsZSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKCJwdG0iKSAlPiUgZmlsdGVyKHB0bT09YXxwdG09PWIpDQp9DQprbml0cjo6a2FibGUodGFibGVzKQ0KYGBgDQoNCiMgUExPVFMNCg0KIyMgTGluZXBsb3RzDQoNCiMjIyBQVE0gLSBsZXZlbA0KDQpgYGB7ciwgZmlnLndpZHRoPTE4LCBmaWcuaGVpZ2h0PTEwfQ0KcHRtX2xpc3QxIDwtIGMoKQ0KZm9yIChjb250cmFzdCBpbiBjb250cmFzdHMpew0Kc2lnVGFibGUgPC0gcm93RGF0YShwZVtbInB0bVJlbCJdXSlbW2NvbnRyYXN0XV0gJT4lIGZpbHRlcihhZGpQdmFsPDAuMDUpDQpwdG1fbGlzdDEgPC0gYyhwdG1fbGlzdDEsIHJvd25hbWVzKHNpZ1RhYmxlKSkNCn0NCnB0bV9saXN0MSA8LSB1bmlxdWUocHRtX2xpc3QxKQ0KDQpwbG90cyA8LSBsaXN0KCkNCmZvciAoaSBpbiBwdG1fbGlzdDEpew0KcHJvdF8gPSBzdHJfc3BsaXQoaSwgIiAiKVtbMV1dWzFdDQpzaXRlXyA9IHN0cl9zcGxpdF9maXhlZChpLCAiICIsIDIpWywyXQ0KDQpwZXBmb3JtX2RmIDwtIGxvbmdGb3JtYXQocGVbLCwicGVwZm9ybVJlbCJdLCByb3d2YXJzID0gYygiTGVhZGluZy5yYXpvci5wcm90ZWluIiwgInB0bSIpLCBjb2x2YXJzID0gYygiY29uZGl0aW9uIiwgInN1YnNldCIpKSAlPiUgYXMuZGF0YS5mcmFtZSgpDQpwZXBmb3JtX2RmIDwtIHBlcGZvcm1fZGYgJT4lIGZpbHRlcihMZWFkaW5nLnJhem9yLnByb3RlaW4gPT0gcHJvdF8pDQpwZXBmb3JtX2RmIDwtIHBlcGZvcm1fZGYgJT4lIGZpbHRlcihncmVwbChzaXRlXywgcHRtLCBmaXhlZCA9IFQpKQ0KcGVwZm9ybV9kZiRGZWF0dXJlVHlwZSA8LSAiUGVwdGlkZSINCnBlcGZvcm1fZGYgPC0gcGVwZm9ybV9kZiAlPiUgYXJyYW5nZShjb25kaXRpb24sIHN1YnNldCwgcm93bmFtZSkNCg0KcHRtX2RmIDwtIGxvbmdGb3JtYXQocGVbLCwicHRtUmVsIl0sIHJvd3ZhcnMgPSBjKCJwcm90ZWluIiwgInB0bSIpLCBjb2x2YXJzID0gYygiY29uZGl0aW9uIiwgInN1YnNldCIpKSAlPiUgYXMuZGF0YS5mcmFtZSgpDQpwdG1fZGYgPC0gcHRtX2RmICU+JSBmaWx0ZXIocHRtID09IGkpDQpwdG1fZGYkRmVhdHVyZVR5cGUgPC0gIlBUTSINCnB0bV9kZiA8LSBwdG1fZGYgJT4lIGFycmFuZ2UoY29uZGl0aW9uLCBzdWJzZXQsIHJvd25hbWUpDQoNCnB0bV9lc3RpbWF0ZSA8LSBwdG1fZGYgJT4lIHNlbGVjdChjKCJwcmltYXJ5IiwgImNvbG5hbWUiLCAiY29uZGl0aW9uIiwgInN1YnNldCIpKSAlPiUNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShyb3duYW1lID0gcGFzdGUocHRtX2RmJHJvd25hbWUsICJlc3RpbWF0ZSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB0bSA9IHBhc3RlKHB0bV9kZiRwdG0sICJlc3RpbWF0ZSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFByb3RlaW4gPSBwYXN0ZShwdG1fZGYkUHJvdGVpbiwgImVzdGltYXRlIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRmVhdHVyZVR5cGUgPSAiUFRNX2VzdGltYXRlZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBOQSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NheSA9ICJtb2RlbCIpDQpmaXhlZmZlY3RzIDwtIHJvd0RhdGEocGVbWyJwdG1SZWwiXV0pJG1zcXJvYk1vZGVsc1tbdW5pcXVlKHB0bV9kZiRwdG0pXV0gJT4lIGdldENvZWYNCnB0bV9lc3RpbWF0ZVtwdG1fZXN0aW1hdGUkY29uZGl0aW9uPT0iQiImKHB0bV9lc3RpbWF0ZSRzdWJzZXQ9PSJ4IiksXSR2YWx1ZSA8LSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaXhlZmZlY3RzW1siKEludGVyY2VwdCkiXV0NCnB0bV9lc3RpbWF0ZVtwdG1fZXN0aW1hdGUkY29uZGl0aW9uPT0iQiImKHB0bV9lc3RpbWF0ZSRzdWJzZXQ9PSJ5IiksXSR2YWx1ZSA8LSANCiAgIGZpeGVmZmVjdHNbWyIoSW50ZXJjZXB0KSJdXSArIGZpeGVmZmVjdHNbWyJzdWJzZXR5Il1dDQpwdG1fZXN0aW1hdGVbcHRtX2VzdGltYXRlJGNvbmRpdGlvbj09IkEiJihwdG1fZXN0aW1hdGUkc3Vic2V0PT0ieCIpLF0kdmFsdWUgPC0gDQogICBmaXhlZmZlY3RzW1siKEludGVyY2VwdCkiXV0gKyBmaXhlZmZlY3RzW1siY29uZGl0aW9uQSJdXQ0KcHRtX2VzdGltYXRlW3B0bV9lc3RpbWF0ZSRjb25kaXRpb249PSJBIiYocHRtX2VzdGltYXRlJHN1YnNldD09InkiKSxdJHZhbHVlIDwtIA0KICAgZml4ZWZmZWN0c1tbIihJbnRlcmNlcHQpIl1dICsgZml4ZWZmZWN0c1tbImNvbmRpdGlvbkEiXV0gKyBmaXhlZmZlY3RzW1siY29uZGl0aW9uQTpzdWJzZXR5Il1dICsgZml4ZWZmZWN0c1tbInN1YnNldHkiXV0NCg0KcGxvdF9kZiA8LSByYmluZGxpc3QobGlzdChwZXBmb3JtX2RmLCBwdG1fZGYsIHB0bV9lc3RpbWF0ZSksIGZpbGwgPSBUUlVFKQ0KcGxvdF9wb2ludHMgPC0gcmJpbmRsaXN0KGxpc3QocGVwZm9ybV9kZiwgcHRtX2RmKSwgZmlsbCA9IFRSVUUpDQoNCnBsb3RfZGYkcHJpbWFyeSA8LSBmb3JjYXRzOjpmY3RfaW5vcmRlcihwbG90X2RmJHByaW1hcnkpDQoNCnBsb3RzW1tpXV0gPC0gcGxvdF9kZiAlPiUgZ2dwbG90KCkgKw0KICBnZW9tX2xpbmUoYWVzKHggPSBwcmltYXJ5LCB5ID0gdmFsdWUgLCBncm91cCA9IHJvd25hbWUsIGNvbG9yID0gRmVhdHVyZVR5cGUpLCBzaXplID0gMikgKw0KICBnZW9tX3BvaW50KGRhdGEgPSBwbG90X3BvaW50cywgYWVzKHggPSBwcmltYXJ5LCB5ID0gdmFsdWUgLCBncm91cCA9IHJvd25hbWUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gRmVhdHVyZVR5cGUpLCBzaXplID0gNSkgKw0KICBnZW9tX3ZsaW5lKGRhdGE9ZGF0YS5mcmFtZSh4ID0gYyg0My41LCAxNy41LCA1Ni41KSksDQogICAgICAgICAgICAgYWVzKHhpbnRlcmNlcHQ9YXMubnVtZXJpYyh4KSksIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKCJQZXB0aWRlIiA9ICIjQzNDM0MzIiwgIlBUTSIgPSAicGFsZWdyZWVuMyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUFRNX2VzdGltYXRlZCIgPSAic2xhdGVibHVlMyIpKSArDQogIGxhYnModGl0bGUgPSBpLCB4ID0gIlNhbXBsZSIsIHkgPSAiSW50ZW5zaXR5IikgKw0KICB0aGVtZV9saWdodCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA2MCwgaGp1c3Q9MSwgc2l6ZSA9IDEwKSwNCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTkpLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgIHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOSksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gIGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gYygwLjUsIDAuMSkpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMjQsIHkgPSA2LjUsIGxhYmVsID0gIkIiLCBzaXplID0gOCkgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSA3MCwgeSA9IDYuNSwgbGFiZWwgPSAiQSIsIHNpemUgPSA4KSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDksIHkgPSA2LCBsYWJlbCA9ICJ4Iiwgc2l6ZSA9IDcpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMzAsIHkgPSA2LCBsYWJlbCA9ICJ5Iiwgc2l6ZSA9IDcpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gNDkuNSwgeSA9IDYsIGxhYmVsID0gIngiLCBzaXplID0gNykgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSA3MywgeSA9IDYsIGxhYmVsID0gInkiLCBzaXplID0gNykgKw0KICB5bGltKC02LCA2LjUpDQoNCn0NCnBsb3RzDQpgYGANCg0KDQojIyMgUGVwdGlkb2Zvcm0gbGV2ZWwNCg0KDQoNCmBgYHtyLCBmaWcud2lkdGg9MTgsIGZpZy5oZWlnaHQ9MTB9DQpwZXBmX2xpc3QxIDwtIGMoKQ0KZm9yIChjb250cmFzdCBpbiBjb250cmFzdHMpew0Kc2lnVGFibGUgPC0gcm93RGF0YShwZVtbInBlcGZvcm1SZWwiXV0pW1tjb250cmFzdF1dICU+JSBmaWx0ZXIoYWRqUHZhbDwwLjA1KQ0KcGVwZl9saXN0MSA8LSBjKHBlcGZfbGlzdDEsIHJvd25hbWVzKHNpZ1RhYmxlKSkNCn0NCnBlcGZfbGlzdDEgPC0gdW5pcXVlKHBlcGZfbGlzdDEpDQoNCnBsb3RzIDwtIGxpc3QoKQ0KZm9yIChpIGluIHBlcGZfbGlzdDEpew0KcHJvdF8gPSByb3dEYXRhKHBlW1sicGVwZm9ybVJlbCJdXSlbaSxdW1siTGVhZGluZy5yYXpvci5wcm90ZWluIl1dDQpzaXRlXyA9IHJvd0RhdGEocGVbWyJwZXBmb3JtUmVsIl1dKVtpLF1bWyJtb2QiXV0NCnNpdGVzXyA9IHN0cnNwbGl0KHNpdGVfLCAiLCAiKVtbMV1dDQpmb3IgKHNpdGVfIGluIHNpdGVzXyl7DQpwdG1fID0gcGFzdGUocHJvdF8sIHNpdGVfLCBjb2xsYXBzZSA9ICIgIikNCnByaW50KHB0bV8pDQoNCnBlcGZvcm1fZGYgPC0gbG9uZ0Zvcm1hdChwZVssLCJwZXBmb3JtUmVsIl0sIHJvd3ZhcnMgPSBjKCJMZWFkaW5nLnJhem9yLnByb3RlaW4iLCAicHRtIiksIGNvbHZhcnMgPSBjKCJjb25kaXRpb24iLCAic3Vic2V0IikpICU+JSBhcy5kYXRhLmZyYW1lKCkNCnBlcGZvcm1fZGYgPC0gcGVwZm9ybV9kZiAlPiUgZmlsdGVyKExlYWRpbmcucmF6b3IucHJvdGVpbiA9PSBwcm90XykNCnBlcGZvcm1fZGYgPC0gcGVwZm9ybV9kZiAlPiUgZmlsdGVyKGdyZXBsKHNpdGVfLCBwdG0sIGZpeGVkID0gVCkpDQpwZXBmb3JtX2RmJEZlYXR1cmVUeXBlIDwtICJQZXB0aWRlIg0KcGVwZm9ybV9kZltwZXBmb3JtX2RmJHJvd25hbWU9PWksXSRGZWF0dXJlVHlwZSA8LSAiU2lnbmlmaWNhbnRQZXB0aWRlIg0KcGVwZm9ybV9kZiA8LSBwZXBmb3JtX2RmICU+JSBhcnJhbmdlKGNvbmRpdGlvbiwgc3Vic2V0LCByb3duYW1lKQ0KDQpwdG1fZGYgPC0gbG9uZ0Zvcm1hdChwZVssLCJwdG1SZWwiXSwgcm93dmFycyA9IGMoInByb3RlaW4iLCAicHRtIiksIGNvbHZhcnMgPSBjKCJjb25kaXRpb24iLCAic3Vic2V0IikpICU+JSBhcy5kYXRhLmZyYW1lKCkNCnB0bV9kZiA8LSBwdG1fZGYgJT4lIGZpbHRlcihwdG0gPT0gcHRtXykNCnB0bV9kZiRGZWF0dXJlVHlwZSA8LSAiUFRNIg0KcHRtX2RmIDwtIHB0bV9kZiAlPiUgYXJyYW5nZShjb25kaXRpb24sIHN1YnNldCwgcm93bmFtZSkNCg0KcHRtX2VzdGltYXRlIDwtIHB0bV9kZiAlPiUgc2VsZWN0KGMoInByaW1hcnkiLCAiY29sbmFtZSIsICJjb25kaXRpb24iLCAic3Vic2V0IikpICU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKHJvd25hbWUgPSBwYXN0ZShwdG1fZGYkcm93bmFtZSwgImVzdGltYXRlIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHRtID0gcGFzdGUocHRtX2RmJHB0bSwgImVzdGltYXRlIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUHJvdGVpbiA9IHBhc3RlKHB0bV9kZiRQcm90ZWluLCAiZXN0aW1hdGUiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGZWF0dXJlVHlwZSA9ICJQVE1fZXN0aW1hdGVkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IE5BLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2F5ID0gIm1vZGVsIikNCmZpeGVmZmVjdHMgPC0gcm93RGF0YShwZVtbInB0bVJlbCJdXSkkbXNxcm9iTW9kZWxzW1t1bmlxdWUocHRtX2RmJHB0bSldXSAlPiUgZ2V0Q29lZg0KcHRtX2VzdGltYXRlW3B0bV9lc3RpbWF0ZSRjb25kaXRpb249PSJCIiYocHRtX2VzdGltYXRlJHN1YnNldD09IngiKSxdJHZhbHVlIDwtIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpeGVmZmVjdHNbWyIoSW50ZXJjZXB0KSJdXQ0KcHRtX2VzdGltYXRlW3B0bV9lc3RpbWF0ZSRjb25kaXRpb249PSJCIiYocHRtX2VzdGltYXRlJHN1YnNldD09InkiKSxdJHZhbHVlIDwtIA0KICAgZml4ZWZmZWN0c1tbIihJbnRlcmNlcHQpIl1dICsgZml4ZWZmZWN0c1tbInN1YnNldHkiXV0NCnB0bV9lc3RpbWF0ZVtwdG1fZXN0aW1hdGUkY29uZGl0aW9uPT0iQSImKHB0bV9lc3RpbWF0ZSRzdWJzZXQ9PSJ4IiksXSR2YWx1ZSA8LSANCiAgIGZpeGVmZmVjdHNbWyIoSW50ZXJjZXB0KSJdXSArIGZpeGVmZmVjdHNbWyJjb25kaXRpb25BIl1dDQpwdG1fZXN0aW1hdGVbcHRtX2VzdGltYXRlJGNvbmRpdGlvbj09IkEiJihwdG1fZXN0aW1hdGUkc3Vic2V0PT0ieSIpLF0kdmFsdWUgPC0gDQogICBmaXhlZmZlY3RzW1siKEludGVyY2VwdCkiXV0gKyBmaXhlZmZlY3RzW1siY29uZGl0aW9uQSJdXSArIGZpeGVmZmVjdHNbWyJjb25kaXRpb25BOnN1YnNldHkiXV0rIGZpeGVmZmVjdHNbWyJzdWJzZXR5Il1dDQoNCg0KcGxvdF9kZiA8LSByYmluZGxpc3QobGlzdChwZXBmb3JtX2RmLCBwdG1fZGYsIHB0bV9lc3RpbWF0ZSksIGZpbGwgPSBUUlVFKQ0KcGxvdF9wb2ludHMgPC0gcmJpbmRsaXN0KGxpc3QocGVwZm9ybV9kZiwgcHRtX2RmKSwgZmlsbCA9IFRSVUUpDQoNCiMgcGxvdF9kZltwbG90X2RmJEZlYXR1cmVUeXBlID09ICdQVE0nXVtbJ0ZlYXR1cmVUeXBlJ11dIDwtICJQVE0gU3VtbWFyaXplZCINCiMgcGxvdF9kZltwbG90X2RmJEZlYXR1cmVUeXBlICE9ICdQVE0nXVtbJ0ZlYXR1cmVUeXBlJ11dIDwtICJQVE0gRmVhdHVyZSINCnBsb3RfZGYkcHJpbWFyeSA8LSBmb3JjYXRzOjpmY3RfaW5vcmRlcihwbG90X2RmJHByaW1hcnkpDQoNCnBsb3RzW1twYXN0ZShpLCBzaXRlXyldXSA8LSBwbG90X2RmICU+JSBnZ3Bsb3QoKSArDQogIGdlb21fbGluZShhZXMoeCA9IHByaW1hcnksIHkgPSB2YWx1ZSAsIGdyb3VwID0gcm93bmFtZSwgY29sb3IgPSBGZWF0dXJlVHlwZSksIHNpemUgPTIpICsNCiAgZ2VvbV9wb2ludChkYXRhID0gcGxvdF9wb2ludHMsIGFlcyh4ID0gcHJpbWFyeSwgeSA9IHZhbHVlICwgZ3JvdXAgPSByb3duYW1lLCBjb2xvciA9IEZlYXR1cmVUeXBlKSwgc2l6ZSA9IDUpICsNCiAgZ2VvbV92bGluZShkYXRhPWRhdGEuZnJhbWUoeCA9IGMoNDMuNSwgMTcuNSwgNTYuNSkpLA0KICAgICAgICAgICAgIGFlcyh4aW50ZXJjZXB0PWFzLm51bWVyaWMoeCkpLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygiUGVwdGlkZSIgPSAiI0MzQzNDMyIsICJQVE0iID0gInBhbGVncmVlbjMiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTaWduaWZpY2FudFBlcHRpZGUiID0gInZpb2xldHJlZDEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBUTV9lc3RpbWF0ZWQiID0gImxpZ2h0Z29sZGVucm9kIikpICsNCiAgbGFicyh0aXRsZSA9IHBhc3RlKGksIHB0bV8pLCB4ID0gIlNhbXBsZSIsIHkgPSAiSW50ZW5zaXR5IikgKw0KICB0aGVtZV9saWdodCgpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA2MCwgaGp1c3Q9MSwgc2l6ZSA9IDEwKSwNCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTkpLA0KICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgIHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOSksDQogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgbGVnZW5kLnRpdGxlID0gIGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gYygwLjUsIDAuMSkpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMjQsIHkgPSA2LjUsIGxhYmVsID0gIkIiLCBzaXplID0gOCkgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSA3MCwgeSA9IDYuNSwgbGFiZWwgPSAiQSIsIHNpemUgPSA4KSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDksIHkgPSA2LCBsYWJlbCA9ICJ4Iiwgc2l6ZSA9IDcpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMzAsIHkgPSA2LCBsYWJlbCA9ICJ5Iiwgc2l6ZSA9IDcpICsNCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gNDkuNSwgeSA9IDYsIGxhYmVsID0gIngiLCBzaXplID0gNykgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSA3MywgeSA9IDYsIGxhYmVsID0gInkiLCBzaXplID0gNykgKw0KICB5bGltKC02LCA2LjUpDQp9DQp9DQpwbG90cw0KYGBgDQoNCg==